首页 > 代码库 > ACdream 1103 瑶瑶正式成为CEO(树链剖分+费用流)
ACdream 1103 瑶瑶正式成为CEO(树链剖分+费用流)
Problem Description
瑶瑶(tsyao)是某知名货运公司(顺丰)的老板,这个公司很大,货物运输量极大,因此公司修建了许多交通设施,掌控了一个国家的交通运输。
这个国家有n座城市,公司的总部在1号城市。
公司下管辖的有m条道路和n-1段火车线路。
这m条道路和n-1条火车线路都可以用u来表示起点,v来表示终点(数据保证m条道路和n-1条火车线路构成有向无环图)。
这n-1段火车道保证从1号城市出发,能够有唯一的一道只包含火车道的线路到达其他n-1座城市。
每条道路和每段火车道都有一个最佳搭载货物值ai,如果要搭载的货物超过了ai,公司需要对经过该路线的超过ai的每单位货物增加bi的维修费用,由于种种原因,如果搭载的货物低于ai,公司需要对少的每单位货物(设该路线有x的货物,则计算为ai-x单位)增加ci的维修费用。当然,每单位货物经过时,会有di的基础维护费用。
这里有两种操作:
C xi yi zi: 随着时间和环境的变化,火车道会受到一些影响,xi到yi的火车道ai会改变zi(新的ai应该为ai+zi),若xi不能到达yi,则将hi到xi和hi到yi的路段ai改变zi(hi为可以到达xi和yi的城市,且不存在fi使得 hi能够到达fi,fi能够到达xi和yi)。
当某火车道的ai值小于0时,我们看做该条火车道的最佳搭载货物值为0(当然ai事实上是负数);
Q vi wi: 查询当计划将wi单位货物从1号城市到vi号城市时,该公司需要的最小维护费用。维护费用计算为每条道路和火车道的维护费用的和(SUMbi+SUMci+SUMdi)。
Input
第一行两个整数n,m,用空格隔开。
接下来n-1+m行,每行u,v,ai,bi,ci,di六个整数。
前n-1行表示火车线路,后m行表示道路。
接下来一行为一个整数q。
接下来q行分别为上述两种操作。
Output
对于每次Q操作,输出答案,数据保证答案在int范围内。
题目大意:略。
思路:
——————————————————————————————————————————————————————————————————
扒官方题解:http://tsyao.tk/archives/94
对付修改的话,就用树链剖分就好,然后每次询问跑网络流。
网络流这样建图,先假设我每条边都跑了0的流量,我们先算出跑了0的流量的费用,然后对于一条边,我跑了小于ai的流量的时候,每次增加一点流量,就相当于减小了ci的费用,所以把一条边拆成两条边,一条是费用为-ci+di,上界为ai的边,一条是费用为bi+di,上界为无穷的边。。。
——————————————————————————————————————————————————————————————————
PS:简单的说就是两条SB题合在一起出,这样也脱离不了它是SB题的结果。但是却忘了删一条调试语句导致无限TLE……
代码(1772MS):
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 using namespace std; 7 typedef long long LL; 8 9 const int MAXN = 510; 10 const int MAXV = MAXN; 11 const int MAXE = 2 * (2010 * 2 + MAXN * 2); 12 const int MAXT = MAXN << 2; 13 const int INF = 0x3f3f3f3f; 14 15 struct SPFA_COST_FLOW { 16 int head[MAXV]; 17 int to[MAXE], next[MAXE], cap[MAXE], flow[MAXE]; 18 LL cost[MAXE]; 19 int n, m, ecnt, st, ed; 20 21 void init(int n) { 22 this->n = n; 23 memset(head + 1, -1, n * sizeof(int)); 24 ecnt = 0; 25 } 26 27 void add_edge(int u, int v, int f, LL c) { 28 to[ecnt] = v; cap[ecnt] = f; cost[ecnt] = c; next[ecnt] = head[u]; head[u] = ecnt++; 29 to[ecnt] = u; cap[ecnt] = 0; cost[ecnt] = -c; next[ecnt] = head[v]; head[v] = ecnt++; 30 } 31 32 void clear() { 33 memset(flow, 0, ecnt * sizeof(int)); 34 } 35 36 LL dis[MAXV]; 37 int pre[MAXV]; 38 bool vis[MAXV]; 39 40 bool spfa() { 41 memset(vis + 1, 0, n * sizeof(bool)); 42 memset(dis, 0x3f, (n + 1) * sizeof(LL)); 43 queue<int> que; que.push(st); 44 dis[st] = 0; 45 while(!que.empty()) { 46 int u = que.front(); que.pop(); 47 vis[u] = false; 48 for(int p = head[u]; ~p; p = next[p]) { 49 int v = to[p]; 50 if(cap[p] - flow[p] && dis[u] + cost[p] < dis[v]) { 51 dis[v] = dis[u] + cost[p]; 52 pre[v] = p; 53 if(!vis[v]) { 54 que.push(v); 55 vis[v] = true; 56 } 57 } 58 } 59 } 60 return dis[ed] < dis[0]; 61 } 62 63 LL maxFlow, minCost; 64 65 LL min_cost_flow(int ss, int tt) { 66 st = ss, ed = tt; 67 maxFlow = minCost = 0; 68 while(spfa()) { 69 int u = ed, tmp = INF; 70 while(u != st) { 71 tmp = min(tmp, cap[pre[u]] - flow[pre[u]]); 72 u = to[pre[u] ^ 1]; 73 } 74 u = ed; 75 while(u != st) { 76 flow[pre[u]] += tmp; 77 flow[pre[u] ^ 1] -= tmp; 78 u = to[pre[u] ^ 1]; 79 } 80 maxFlow += tmp; 81 minCost += tmp * dis[ed]; 82 } 83 return minCost; 84 } 85 } G; 86 87 struct Tree { 88 struct Edge { 89 int a, b, c, d, u, v; 90 void read() { 91 scanf("%d%d%d%d%d%d", &u, &v, &a, &b, &c, &d); 92 } 93 } tree[MAXN], edge[MAXE]; 94 int tid[MAXN], eid[MAXN], size[MAXN], son[MAXN], top[MAXN], dep[MAXN], fa[MAXN]; 95 int n, m, q; 96 97 int head[MAXV], pre[MAXV], ecnt, dfs_clock; 98 int to[MAXE], next[MAXE], id[MAXE]; 99 LL add[MAXT];100 101 void init() {102 memset(head + 1, -1, n * sizeof(int));103 ecnt = dfs_clock = 0;104 }105 106 void add_edge(int u, int v, int i) {107 to[ecnt] = v; id[ecnt] = i; next[ecnt] = head[u]; head[u] = ecnt++;108 to[ecnt] = u; id[ecnt] = i; next[ecnt] = head[v]; head[v] = ecnt++;109 }110 111 void dfs_size(int u, int f, int depth) {112 size[u] = 1; dep[u] = depth; fa[u] = f;113 int maxsize = son[u] = 0;114 for(int p = head[u]; ~p; p = next[p]) {115 int v = to[p];116 if(v == f) continue;117 pre[v] = p;118 dfs_size(v, u, depth + 1);119 size[u] += size[v];120 if(size[v] > maxsize) {121 maxsize = size[v];122 son[u] = v;123 }124 }125 }126 127 void dfs_heavy_edge(int u, int ancestor) {128 tid[u] = ++dfs_clock; eid[dfs_clock] = id[pre[u]];129 top[u] = ancestor;130 if(son[u]) dfs_heavy_edge(son[u], ancestor);131 for(int p = head[u]; ~p; p = next[p]) {132 int v = to[p];133 if(v == fa[u] || v == son[u]) continue;134 dfs_heavy_edge(v, v);135 }136 }137 138 #define ll (x << 1)139 #define rr (ll | 1)140 #define mid ((l + r) >> 1)141 142 void pushdown(int x) {143 if(add[x]) {144 add[ll] += add[x];145 add[rr] += add[x];146 add[x] = 0;147 }148 }149 150 void pushadd(int x, int l, int r) {151 if(l == r) {152 if(l > 1) tree[eid[l]].a += add[x];153 add[x] = 0;154 } else {155 pushdown(x);156 pushadd(ll, l, mid);157 pushadd(rr, mid + 1, r);158 }159 }160 161 void modify(int x, int l, int r, int a, int b, int val) {162 if(a <= l && r <= b) {163 add[x] += val;164 } else {165 if(a <= mid) modify(ll, l, mid, a, b, val);166 if(mid < b) modify(rr, mid + 1, r, a, b, val);167 }168 }169 170 void modify(int x, int y, int val) {171 while(top[x] != top[y]) {172 if(dep[top[x]] < dep[top[y]]) swap(x, y);173 modify(1, 1, n, tid[top[x]], tid[x], val);174 x = fa[top[x]];175 }176 if(x != y) {177 if(dep[x] < dep[y]) swap(x, y);178 modify(1, 1, n, tid[son[y]], tid[x], val);179 }180 }181 182 int gid[MAXV];183 void initQuery() {184 G.init(n + 1);185 for(int i = 1; i < n; ++i) {186 Edge &t = tree[i];187 gid[i] = G.ecnt;188 G.add_edge(t.u, t.v, max(0, t.a), t.d - t.c);189 G.add_edge(t.u, t.v, INF, t.d + t.b);190 }191 for(int i = 0; i < m; ++i) {192 Edge &t = edge[i];193 G.add_edge(t.u, t.v, max(0, t.a), t.d - t.c);194 G.add_edge(t.u, t.v, INF, t.d + t.b);195 }196 G.add_edge(n + 1, 1, 0, 0);197 }198 199 int query(int tt, int val) {200 int ss = n + 1;201 pushadd(1, 1, n);202 LL sum = 0;203 for(int i = 1; i < n; ++i) {204 Edge &t = tree[i];205 sum += t.c * max(0, t.a);206 G.cap[gid[i]] = max(0, t.a);207 }208 for(int i = 0; i < m; ++i) {209 Edge &t = edge[i];210 sum += t.c * max(0, t.a);211 }212 G.cap[G.ecnt - 2] = val;213 G.clear();214 return sum + G.min_cost_flow(ss, tt);215 }216 217 void work() {218 scanf("%d%d", &n, &m);219 for(int i = 1; i < n; ++i) tree[i].read();220 for(int i = 0; i < m; ++i) edge[i].read();221 init();222 initQuery();223 for(int i = 1; i < n; ++i) add_edge(tree[i].u, tree[i].v, i);224 dfs_size(1, 0, 1);225 dfs_heavy_edge(1, 1);226 scanf("%d", &q);227 char op;228 for(int i = 0, a, b, c; i < q; ++i) {229 scanf(" %c", &op);230 if(op == ‘Q‘) {231 scanf("%d%d", &a, &b);232 printf("%d\n", query(a, b));233 } else {234 scanf("%d%d%d", &a, &b, &c);235 modify(a, b, c);236 }237 }238 }239 } T;240 241 int main() {242 T.work();243 }