首页 > 代码库 > 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 }
View Code