loj #117. 有源汇有上下界最小流
Posted HWIM
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了loj #117. 有源汇有上下界最小流相关的知识,希望对你有一定的参考价值。
有源汇有上下界最小流,->上下界网络流
注意细节,边数组也要算上后加到SS,TT边。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 7 using namespace std; 8 9 const int N = 150010; 10 const int INF = 1e9; 11 12 struct Edge{ 13 int to,nxt,c; 14 }e[500100]; 15 int head[N],dis[N],cur[N],M[N]; 16 int q[500100],L,R; 17 int tot = 1,n,m,S,T,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) 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 n = read(),m = read(); 76 int s = read(),t = read(); 77 int ss = n + 1,tt = n + 2; 78 for (int i=1; i<=m; ++i) { 79 int u = read(),v = read(),b = read(),c = read(); 80 add_edge(u,v,c-b); 81 add_edge(v,u,0); 82 M[u] -= b;M[v] += b; 83 } 84 for (int i=1; i<=n; ++i) { 85 if (M[i] > 0) add_edge(ss,i,M[i]),add_edge(i,ss,0),Sum += M[i]; 86 if (M[i] < 0) add_edge(i,tt,-M[i]),add_edge(tt,i,0); 87 } 88 add_edge(t,s,INF); //- 89 add_edge(s,t,0); 90 if (dinic(ss,tt) != Sum) { 91 printf("please go home to sleep"); 92 return 0; 93 } 94 int ans = e[tot].c; 95 e[tot].c = 0;e[tot ^ 1].c = 0; 96 ans -= dinic(t,s); 97 printf("%d",ans); 98 return 0; 99 }
以上是关于loj #117. 有源汇有上下界最小流的主要内容,如果未能解决你的问题,请参考以下文章