loj #116. 有源汇有上下界最大流
Posted HWIM
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了loj #116. 有源汇有上下界最大流相关的知识,希望对你有一定的参考价值。
有源汇有上下界最大流,->上下界网络流
注意细节,重置cur和dis数组时,有n+2个点
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #include<iostream> 6 7 using namespace std; 8 9 const int N = 10010; 10 const int INF = 1e9; 11 12 struct Edge { 13 int to,nxt,c; 14 }e[100100]; 15 int head[N],dis[N],cur[N],M[N]; 16 int q[100100],L,R; 17 int n,m,S,T,tot = 1,Sum; 18 19 inline char nc() { 20 static char buf[100000],*p1 = buf,*p2 = buf; 21 return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 22 } 23 inline int read() { 24 int x = 0,f = 1;char ch = nc(); 25 for (; ch<\'0\'||ch>\'9\'; ch=nc()) if(ch==\'-\') f=-1; 26 for (; ch>=\'0\'&&ch<=\'9\'; ch=nc()) x=x*10+ch-\'0\'; 27 return x * f; 28 } 29 void add_edge(int u,int v,int c) { 30 e[++tot].to = v,e[tot].c = c,e[tot].nxt = head[u],head[u] = tot; 31 } 32 bool bfs() { 33 for (int i=1; i<=n+2; ++i) // n+2 34 cur[i] = head[i],dis[i] = -1; 35 L = 1,R = 0; 36 q[++R] = S; 37 dis[S] = 0; 38 while (L <= R) { 39 int u = q[L++]; 40 for (int i=head[u]; i; i=e[i].nxt) { 41 int v = e[i].to; 42 if (dis[v] == -1 && e[i].c > 0) { 43 dis[v] = dis[u] + 1; 44 q[++R] = v; 45 if (v == T) return true; 46 } 47 } 48 } 49 return false; 50 } 51 int dfs(int u,int flow) { 52 if (u == T) return flow; 53 int used = 0; 54 for (int &i=cur[u]; i; i=e[i].nxt) { 55 int v = e[i].to; 56 if (dis[v] == dis[u] + 1 && e[i].c > 0) { 57 int tmp = dfs(v,min(e[i].c,flow-used)); 58 if (tmp > 0) { 59 e[i].c -= tmp;e[i^1].c += tmp; 60 used += tmp; 61 if (used == flow) break; 62 } 63 } 64 } 65 if (used != flow) dis[u] = -1; 66 return used; 67 } 68 int dinic(int s,int t) { 69 S = s,T = t; 70 int ans = 0; 71 while (bfs()) ans += dfs(S,INF); 72 return ans; 73 } 74 int main () { 75 freopen("1.txt","r",stdin); 76 n = read(),m = read(); 77 int s = read(),t = read(); 78 int ss = n+1,tt = n+2; 79 for (int i=1; i<=m; ++i) { 80 int u = read(),v = read(),b = read(),c = read(); 81 add_edge(u,v,c-b); 82 add_edge(v,u,0); 83 M[u] -= b;M[v] += b; 84 } 85 for (int i=1; i<=n; ++i) { 86 if (M[i] > 0) add_edge(ss,i,M[i]),add_edge(i,ss,0),Sum += M[i]; 87 if (M[i] < 0) add_edge(i,tt,-M[i]),add_edge(tt,i,0); 88 } 89 add_edge(t,s,INF); 90 add_edge(s,t,0); 91 if (dinic(ss,tt) != Sum) { 92 puts("please go home to sleep"); 93 return 0; 94 } 95 int ans = e[tot].c; 96 e[tot].c = 0;e[tot ^ 1].c = 0; 97 ans += dinic(s,t); 98 printf("%d\\n",ans); 99 return 0; 100 }
以上是关于loj #116. 有源汇有上下界最大流的主要内容,如果未能解决你的问题,请参考以下文章