SGU176 Flow construction
http://acm.sgu.ru/problem.php?contest=0&problem=176
有源汇上下界最小流,可以选择跟有源汇上下界最大流一样的建图方式,然后用二分去二分t->s这条边的流量,最小的可行流就是答案。
也可以这样:
跟无源汇最大流建图一样,然后不添加t->s的边
对ss->tt求最大流,然后添加t->s的边,求ss->tt最大流,若是满流,则t->s的流量就是最小流
PS:记录一下:SGU的ID是068720
第二种建图方式:
1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #include<cstring> 5 #include<iostream> 6 #define inf 0x7fffffff 7 const int maxn=110; 8 const int maxe=maxn*maxn+10; 9 int tot,go[maxe],first[maxn],next[maxe],flow[maxe]; 10 int op[maxe],id[maxe],n,m,du[maxn],cnt[maxn],dis[maxn]; 11 int dn[maxe]; 12 int read(){ 13 int t=0,f=1;char ch=getchar(); 14 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 15 while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} 16 return t*f; 17 } 18 void insert(int x,int y,int z){ 19 tot++; 20 go[tot]=y; 21 next[tot]=first[x]; 22 first[x]=tot; 23 flow[tot]=z; 24 } 25 void add(int x,int y,int z){ 26 insert(x,y,z);op[tot]=tot+1; 27 insert(y,x,0);op[tot]=tot-1; 28 } 29 int dfs(int x,int f,int S,int T,int nodes){ 30 if (x==T) return f; 31 int mn=nodes,sum=0; 32 for (int i=first[x];i;i=next[i]){ 33 int pur=go[i]; 34 if (flow[i]&&dis[pur]+1==dis[x]){ 35 int F=std::min(f-sum,flow[i]); 36 int save=dfs(pur,F,S,T,nodes); 37 flow[i]-=save; 38 flow[op[i]]+=save; 39 sum+=save; 40 if (f==sum||dis[S]>=nodes) return sum; 41 } 42 if (flow[i]) mn=std::min(mn,dis[pur]); 43 } 44 if (sum==0){ 45 cnt[dis[x]]--; 46 if (cnt[dis[x]]==0) dis[S]=nodes; 47 else { 48 dis[x]=mn+1; 49 cnt[dis[x]]++; 50 } 51 } 52 return sum; 53 } 54 int mxflow(int S,int T,int nodes){ 55 int res=0; 56 for (int i=0;i<=nodes;i++) cnt[i]=dis[i]=0; 57 while (dis[S]<nodes) res+=dfs(S,inf,S,T,nodes); 58 return res; 59 } 60 int main(){ 61 int s,t; 62 n=read();m=read(); 63 s=0;t=n+1; 64 for (int i=1;i<=m;i++){ 65 int u=read(),v=read(),c=read(),pd=read(); 66 if (pd){ 67 du[u]-=c; 68 du[v]+=c; 69 add(u,v,0); 70 dn[i]=c;id[i]=tot; 71 }else{ 72 add(u,v,c); 73 dn[i]=0;id[i]=tot; 74 } 75 } 76 int sum=0; 77 for (int i=1;i<=n;i++) 78 if (du[i]<0) add(i,t,-du[i]); 79 else add(s,i,du[i]),sum+=du[i]; 80 int sum1=mxflow(s,t,t+1); 81 add(n,1,inf); 82 int sum2=mxflow(s,t,t+1); 83 int sx=0; 84 for (int i=first[s];i;i=next[i]){ 85 if (flow[i]){ 86 puts("Impossible"); 87 return 0; 88 } 89 } 90 printf("%d\n",flow[tot]); 91 for (int i=1;i<=m;i++) 92 printf("%d ",flow[id[i]]+dn[i]); 93 94 return 0; 95 }