您的位置:首页 > 其它

SGU176 Flow construction

2016-06-27 20:21 323 查看
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

第二种建图方式:

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<iostream>
#define inf 0x7fffffff
const int maxn=110;
const int maxe=maxn*maxn+10;
int tot,go[maxe],first[maxn],next[maxe],flow[maxe];
int op[maxe],id[maxe],n,m,du[maxn],cnt[maxn],dis[maxn];
int dn[maxe];
int read(){
int t=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
return t*f;
}
void insert(int x,int y,int z){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
flow[tot]=z;
}
void add(int x,int y,int z){
insert(x,y,z);op[tot]=tot+1;
insert(y,x,0);op[tot]=tot-1;
}
int dfs(int x,int f,int S,int T,int nodes){
if (x==T) return f;
int mn=nodes,sum=0;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (flow[i]&&dis[pur]+1==dis[x]){
int F=std::min(f-sum,flow[i]);
int save=dfs(pur,F,S,T,nodes);
flow[i]-=save;
flow[op[i]]+=save;
sum+=save;
if (f==sum||dis[S]>=nodes) return sum;
}
if (flow[i]) mn=std::min(mn,dis[pur]);
}
if (sum==0){
cnt[dis[x]]--;
if (cnt[dis[x]]==0) dis[S]=nodes;
else {
dis[x]=mn+1;
cnt[dis[x]]++;
}
}
return sum;
}
int mxflow(int S,int T,int nodes){
int res=0;
for (int i=0;i<=nodes;i++) cnt[i]=dis[i]=0;
while (dis[S]<nodes) res+=dfs(S,inf,S,T,nodes);
return res;
}
int main(){
int s,t;
n=read();m=read();
s=0;t=n+1;
for (int i=1;i<=m;i++){
int u=read(),v=read(),c=read(),pd=read();
if (pd){
du[u]-=c;
du[v]+=c;
add(u,v,0);
dn[i]=c;id[i]=tot;
}else{
add(u,v,c);
dn[i]=0;id[i]=tot;
}
}
int sum=0;
for (int i=1;i<=n;i++)
if (du[i]<0) add(i,t,-du[i]);
else add(s,i,du[i]),sum+=du[i];
int sum1=mxflow(s,t,t+1);
add(n,1,inf);
int sum2=mxflow(s,t,t+1);
int sx=0;
for (int i=first[s];i;i=next[i]){
if (flow[i]){
puts("Impossible");
return 0;
}
}
printf("%d\n",flow[tot]);
for (int i=1;i<=m;i++)
printf("%d ",flow[id[i]]+dn[i]);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: