SGU176 Flow construction

时间:2023-03-09 16:32:15
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

第二种建图方式:

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