标签:
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1314
题意:给出N个点,M条边的有向图,每条边的有上下界规定,问是否存在一个可行流满足条件,如果满足输出YES并输出每条边的流量。
如果不满足输出NO。
根据周源的《一种简易的方法求解流量有上下界的网络中网络流问题》
无源汇上下界网络流的做法是:
设边u->v的下界是B(u,v),上界是C(u,v)。
设M(i)为对于i结点的流入i的下界总和-流出i的下界总和。
增设源点s和汇点t。
如果M(i)>=0 连边s->i,容量为M(i)。
如果M(i)<0 连边i->t,容量为-M(i)。
对于图中的原来的边u-v,连边u->v,容量为C(u,v)-B(u,v)。
然后求最大流。如果对于源点出发的所有边都满流,则说明存在一个可行流满足条件。
1 #include <bits/stdc++.h> 2 using namespace std; 3 int N, M; 4 #define maxn 210 5 const int inf = 0x3f3f3f3f; 6 struct Edge 7 { 8 int from, to, cap, flow; 9 Edge(int f, int t, int c, int fl) 10 { 11 from = f; to = t; cap = c; flow = fl; 12 } 13 }; 14 vector <Edge> edges; 15 vector <int> G[maxn]; 16 int cur[maxn], vis[maxn], d[maxn]; 17 int n, m, s, t; 18 void AddEdge(int from, int to, int cap) 19 { 20 edges.push_back(Edge(from, to, cap, 0)); 21 edges.push_back(Edge(to, from, 0, 0)); 22 m = edges.size(); 23 G[from].push_back(m-2); 24 G[to].push_back(m-1); 25 } 26 bool bfs() 27 { 28 memset(vis, 0, sizeof(vis)); 29 vis[s] = 1; 30 d[s] = 0; 31 queue <int> q; 32 q.push(s); 33 while(!q.empty()) 34 { 35 int u = q.front(); q.pop(); 36 for(int i = 0; i < G[u].size(); i++) 37 { 38 Edge &e = edges[G[u][i]]; 39 if(!vis[e.to] && e.cap > e.flow) 40 { 41 vis[e.to] = 1; 42 d[e.to] = d[u]+1; 43 q.push(e.to); 44 } 45 } 46 } 47 return vis[t]; 48 } 49 int dfs(int x, int a) 50 { 51 if(x == t || a == 0) return a; 52 int flow = 0, f; 53 for(int &i = cur[x]; i < G[x].size(); i++) 54 { 55 Edge &e = edges[G[x][i]]; 56 if(d[x]+1 == d[e.to] && (f = dfs(e.to, min(e.cap - e.flow, a))) > 0) 57 { 58 e.flow += f; 59 edges[G[x][i]^1].flow -= f; 60 flow += f; 61 a -= f; 62 if(a == 0) break; 63 } 64 } 65 return flow; 66 } 67 int MaxFlow() 68 { 69 int flow = 0; 70 while(bfs()) 71 { 72 memset(cur, 0, sizeof(cur)); 73 flow += dfs(s, inf); 74 } 75 return flow; 76 } 77 int T; 78 int in[maxn], out[maxn], Mi[maxn]; 79 int low[210*210]; 80 int main() 81 { 82 scanf("%d", &T); 83 while(T--) 84 { 85 edges.clear(); 86 for(int i = s; i <= t; i++) G[i].clear(); 87 scanf("%d%d", &N, &M); 88 s = 0; t = N+1; 89 memset(in, 0, sizeof(in)); 90 memset(out, 0, sizeof(out)); 91 for(int i = 1; i <= M; i++) 92 { 93 int u, v, l, f; 94 scanf("%d%d%d%d", &u, &v, &l, &f); 95 low[i] = l; 96 AddEdge(u, v, f-l); 97 out[u] += l; 98 in[v] += l; 99 } 100 for(int i = 1; i <= N; i++) 101 { 102 Mi[i] = in[i] - out[i]; 103 if(Mi[i] >= 0) AddEdge(s, i, Mi[i]); 104 else AddEdge(i, t, -Mi[i]); 105 } 106 int flow = MaxFlow(); 107 vector <int> ans; 108 bool flag = true; 109 for(int i = 0; i < m; i+=2) 110 { 111 if(edges[i].from == s && edges[i].cap > edges[i].flow) 112 { 113 flag = false; break; 114 } 115 else if(edges[i].from != s && edges[i].to != t) 116 { 117 ans.push_back(edges[i].flow); 118 } 119 } 120 if(flag) 121 { 122 printf("YES\n"); 123 for(int i = 0; i < ans.size(); i++) 124 { 125 printf("%d\n", ans[i]+low[i+1]); 126 } 127 } 128 else printf("NO\n"); 129 } 130 return 0; 131 }
ZOJ 2314 Reactor Cooling 无源汇有上下界网络流
标签:
原文地址:http://www.cnblogs.com/titicia/p/4858680.html