無源匯有上下界限制可行流(循環流)
即每條邊的流量限制為[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 }
?