[BZOJ1834][ZJOI2010]网络扩容(最大流+费用流)
2018-01-01 19:40
501 查看
第一问即为模板最大流。
第二问在跑完最大流的残余网络上继续建图,对于没有满流的边,将其费用置为0。同时对于所有的边<u,v>,再建一条边<u,v>,容量为∞,费用为边<u,v>的扩容费用。
同时,还需要建一个新的源点连向原图中的源点,容量为K,费用为0。
这样,最小的扩容费用就是最小费用最大流。
代码:
第二问在跑完最大流的残余网络上继续建图,对于没有满流的边,将其费用置为0。同时对于所有的边<u,v>,再建一条边<u,v>,容量为∞,费用为边<u,v>的扩容费用。
同时,还需要建一个新的源点连向原图中的源点,容量为K,费用为0。
这样,最小的扩容费用就是最小费用最大流。
代码:
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int N = 2e5 + 5, INF = 0x3f3f3f3f; int n, m, ecnt = 1, nxt , adj , go , cap , dis , lev , yd = 1, hd, len, que , cost , Ans, K, Y , st , Cap ; bool vis , walk ; void add_edge(int u, int v, int w, int x) { nxt[++ecnt] = adj[u]; adj[u] = ecnt; go[ecnt] = v; cap[ecnt] = w; cost[ecnt] = x; st[ecnt] = u; nxt[++ecnt] = adj[v]; adj[v] = ecnt; go[ecnt] = u; cap[ecnt] = 0; cost[ecnt] = -x; st[ecnt] = v; } bool bfs() { int i; for (i = yd; i <= hd; i++) lev[i] = -1; que[len = 1] = yd; lev[yd] = 0; for (i = 1; i <= len; i++) { int u = que[i]; for (int e = adj[u], v; e; e = nxt[e]) if (cap[e] > 0 && lev[v = go[e]] == -1) { lev[v] = lev[u] + 1; que[++len] = v; if (v == hd) return 1; } } return 0; } int dinic(int u, int flow) { if (u == hd) return flow; int res = 0, d; for (int e = adj[u], v; e; e = nxt[e]) if (cap[e] > 0 && lev[u] < lev[v = go[e]]) { d = dinic(v, min(cap[e], flow - res)); if (d) { cap[e] -= d; cap[e ^ 1] += d; res += d; if (res == flow) break; } } if (res != flow) lev[u] = -1; return res; } int solve() { int ans = 0; while (bfs()) ans += dinic(yd, INF); return ans; } bool bfs2() { que[len = 1] = yd; int i; for (i = 1; i <= yd; i++) dis[i] = INF, walk[i] = 0; vis[yd] = 1; dis[yd] = 0; for (i = 1; i <= len; i++) { int u; vis[u = que[i]] = 0; for (int e = adj[u], v; e; e = nxt[e]) if (cap[e] > 0 && dis[u] + cost[e] < dis[v = go[e]]) { dis[v] = dis[u] + cost[e]; if (!vis[v]) vis[v] = 1, que[++len] = v; } } return dis[hd] < INF; } int dinic2(int u, int flow) { if (u == hd) return Ans += flow * dis[hd], flow; walk[u] = 1; int res = 0, delta = 0; for (int e = adj[u], v; e; e = nxt[e]) if (cap[e] > 0 && !walk[v = go[e]] && dis[u] + cost[e] == dis[v]) { delta = dinic2(v, min(cap[e], flow - res)); if (delta) { cap[e] -= delta; cap[e ^ 1] += delta; res += delta; if (res == flow) break; } } return res; } int solve2() { Ans = 0; while (bfs2()) dinic2(yd, INF); return Ans; } inline int read() { int res = 0; bool bo = 0; char c; while (((c = getchar()) < '0' || c > '9') && c != '-'); if (c == '-') bo = 1; else res = c - 48; while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + (c - 48); return bo ? ~res + 1 : res; } int main() { int i, u, v, x, y, ff; n = hd = read(); m = read(); K = read(); for (i = 1; i <= m; i++) u = read(), v = read(), x = read(), y = read(), add_edge(u, v, x, y), Cap[ecnt - 1] = x; printf("%d ", solve()); ff = ecnt; for (i = 2; i <= ff; i += 2) { if (cap[i] > 0) add_edge(st[i], go[i], cap[i], 0), cap[ecnt] = cap[i ^ 1]; cap[i] = INF; cap[i ^ 1] = 0; } yd = hd + 1; add_edge(yd, 1, K, 0); printf("%d\n", solve2()); return 0; }
相关文章推荐
- 【BZOJ】1834: [ZJOI2010]network 网络扩容(最大流+费用流)
- bzoj 1834: [ZJOI2010]network 网络扩容 -- 最大流+费用流
- [BZOJ1834][ZJOI2010]network 网络扩容(最大流+费用流)
- bzoj1834[ZJOI2010]network 网络扩容【最大流+费用流】
- 【bzoj1834】[ZJOI2010]network 网络扩容 最大流+最小费用流
- [bzoj1834][ZJOI2010] 网络扩容 最大流 费用流
- [BZOJ1834][ZJOI2010]network 网络扩容 最大流+费用流
- BZOJ 1834: [ZJOI2010]network 网络扩容(最大流+最小费用最大流)
- BZOJ1834 [ZJOI2010]network 网络扩容 【最大流,费用流】
- [BZOJ1834]ZJOI2010网络扩容|最大流|费用流
- bzoj 1834: [ZJOI2010]network 网络扩容【最大流+最小费用最大流】
- 【最大流】【费用流】bzoj1834 [ZJOI2010]network 网络扩容
- 【最大流/费用流】BZOJ1834-[ZJOI2010]network 网络扩容
- 【BZOJ1834】[ZJOI2010]network 网络扩容 最大流+最小费用流
- [BZOJ1834][ZJOI2010][最大流][最小费用最大流]网络扩容
- 【BZOJ1834】[ZJOI2010]network 网络扩容【最大流】【最小费用最大流】【残量网络】
- bzoj1834 [ZJOI2010]network 网络扩容 最大流+费用流
- bzoj 1834 [ZJOI2010] network 网络扩容 题解
- [BZOJ1834][ZJOI2010]network 网络扩容
- [bzoj1834][ZJOI2010]network 网络扩容