有上下界限制可行流
无源汇有上下界限制可行流(循环流)
即每条边的流量限制为[L,R],判断有没有满足整个网络的可行流。
看看以前学的网络流,实际上它的流量限制为[0,C],现在无非多了一个下限的限制。
网络流的一个重要性质:除了源汇点的点,入流==出流。
本来点是不能存储水的,我们先不妨假设每条边都满足下限,对于某一条边来说,它的出水端的点水量-=L,入水端的点+=L,它的容量变为[0,R-L]。
这时候就会出现有的点水量是正的,另外点的水量是负的,如果能通过导流,使所有点的水量均为0,那么说明存在可行流。
怎么导流?建立一个超级源点s,超级汇点t,s向水量为正的点连边,容量即为水量。水量为负的点向t连边,容量即为水量。(自己脑补)
s到t跑一遍最大流,如果最大流为源点流出的水量之和,则存在可行流。。
有源汇的情况:汇点向源点连一条容量INF的边,即变成了无源汇的情况。
2018沈阳icpc网赛F(裸题):
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<vector> 5 #include<algorithm> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 typedef long long ll; 10 const int MAX_N = 5000; 11 const int MAX_M = 50000; 12 const int INF = 1000000000; 13 struct edge { 14 int v, c, next; 15 } e[MAX_M]; 16 int p[MAX_N], eid; 17 void init() { 18 memset(p, -1, sizeof(p)); 19 eid = 0; 20 } 21 void insert(int u, int v, int c) { 22 e[eid].v = v; 23 e[eid].c = c; 24 e[eid].next = p[u]; 25 p[u] = eid++; 26 } 27 void addedge(int u, int v, int c) { 28 insert(u, v, c); 29 insert(v, u, 0); 30 } 31 int S, T; 32 int d[MAX_N]; 33 bool CountLayer() { 34 memset(d, -1, sizeof(d)); 35 queue<int> q; 36 q.push(S); 37 d[S] = 0; 38 while (!q.empty()) { 39 int u = q.front(); 40 q.pop(); 41 for (int i = p[u]; i != -1; i = e[i].next) { 42 int v = e[i].v; 43 if (e[i].c > 0 && d[v] == -1) { 44 q.push(v); 45 d[v] = d[u] + 1; 46 } 47 } 48 } 49 return (d[T] != -1); 50 } 51 52 ll dfs(int u, int flow) { 53 if (u == T) { 54 return flow; 55 } 56 ll res = 0; 57 for (int i = p[u]; i != -1; i = e[i].next) { 58 int v = e[i].v; 59 if (e[i].c > 0 && d[u] + 1 == d[v]) { 60 ll tmp = dfs(v, min(flow, e[i].c)); 61 flow -= tmp; 62 e[i].c -= tmp; 63 res += tmp; 64 e[i ^ 1].c += tmp; 65 if (flow == 0) { 66 break; 67 } 68 } 69 } 70 if (res == 0) { 71 d[u] = -1; 72 } 73 return res; 74 } 75 76 ll maxflow() { 77 ll res = 0; 78 while (CountLayer()) { 79 res += dfs(S, INF); 80 } 81 return res; 82 } 83 ll def[5000]; 84 int main() 85 { 86 int d=1; 87 int n,m,k; 88 while(cin>>n>>m>>k) 89 { 90 int l,r,u,v; 91 S=n+m+3,T=n+m+4; 92 init(); 93 memset(def,0,sizeof def); 94 scanf("%d%d",&l,&r); 95 for(int i=1;i<=k;i++) 96 { 97 scanf("%d%d",&u,&v); 98 v=v+n; 99 addedge(u, v, 1); 100 } 101 for(int i=1;i<=n;i++) 102 { 103 addedge(n+m+1, i, r-l); 104 def[i]+=l; 105 } 106 for(int i=n+1;i<=n+m;i++) 107 { 108 addedge(i, n+m+2, r-l); 109 def[i]-=l; 110 } 111 addedge(n+m+2,n+m+1,INF); 112 113 ll sum=0; 114 for(int i=1;i<=n+m;i++) 115 { 116 if(def[i]>0) {addedge(S,i,def[i]);sum+=def[i];} 117 else addedge(i,T,-def[i]); 118 } 119 if(sum==maxflow()) printf("Case %d: Yes\n",d++); 120 else printf("Case %d: No\n",d++); 121 } 122 return 0; 123 }