有上下界的网络流总结(未完成)
LOJ上有全套的模板
我们先来看一个最简单的问题,无源无汇可行流
如果没有下限的限制,那么这就是一个普通的网络流问题,考虑我们如何将限制去掉
如果我们每条边已经流过了大于等于下限的流量,我们是不是就,可以相当于去掉了限制
而流量下界是必须流满的,如果找不出一中是每条边的流量满足下界的方案。这显然是无解的
我们考察每一个点必定会流入的流量和必定会流出的流量,如果相等,显然是可取的,但是显然会有流入的最小流量不等于流出的最小流量的情况
这样就不满足流量平衡了
所以我们要新增一个原点,向所有最小流入量小于最小流出流量的点连一条流量上界为两者差值的边
我们再建立一个汇点,接受所有最小流入量大于最小流出量的流量
由于这些流量是必须满足的,所以这些边都必须满流,如果不满流,就是无解
无源无汇可行流
1 # include<iostream> 2 # include<cstdio> 3 # include<cmath> 4 # include<algorithm> 5 # include<cstring> 6 # include<queue> 7 using namespace std; 8 const int mn = 205; 9 const int inf = 0x3f3f3f3f; 10 struct edge{int to,next,flow,cup;}; 11 edge e[10200*10]; 12 int head[mn],edge_max=1; 13 void add(int x,int y,int z) 14 { 15 //printf("%d %d\n",x,y); 16 e[++edge_max].to=y; 17 e[edge_max].flow=e[edge_max].cup=z; 18 e[edge_max].next=head[x]; 19 head[x]=edge_max; 20 } 21 int n,m; 22 int B[mn],low[10200*10]; 23 int cur[mn],deep[mn]; 24 queue<int> q; 25 bool bfs(int x,int y) 26 { 27 memset(deep,0,sizeof(deep)); 28 q.push(x); 29 deep[x]=1; 30 while(!q.empty()) 31 { 32 int u=q.front(); 33 q.pop(); 34 for(int i=head[u];i;i=e[i].next) 35 { 36 if(e[i].flow>0 && deep[e[i].to]==0) 37 { 38 deep[e[i].to]=deep[u]+1; 39 q.push(e[i].to); 40 } 41 } 42 } 43 /*for(int i=1;i<=y;i++) 44 printf("%d ",deep[i]); 45 printf("\n");*/ 46 return deep[y]!=0; 47 } 48 int dfs(int x,int dist,int y) 49 { 50 if(x==y) 51 return dist; 52 for(int &i=cur[x];i;i=e[i].next) 53 { 54 if(e[i].flow>0 && deep[e[i].to]==deep[x]+1) 55 { 56 int di=dfs(e[i].to,min(e[i].flow,dist),y); 57 if(di>0) 58 { 59 e[i].flow-=di; 60 e[i^1].flow+=di; 61 return di; 62 } 63 } 64 } 65 return 0; 66 } 67 int dinic(int x,int y) 68 { 69 int ret=0; 70 while(bfs(x,y)) 71 { 72 //memset(cur,0,sizeof(cur)); 73 for(int i=1;i<=y;i++) 74 cur[i]=head[i]; 75 while(int k=dfs(x,inf,y)) 76 { 77 //printf("%d\n",k); 78 ret+=k; 79 } 80 //printf("%d\n",ret); 81 } 82 return ret; 83 } 84 int main() 85 { 86 int x,y,a,b; 87 scanf("%d%d",&n,&m); 88 for(int i=1;i<=m;i++) 89 { 90 scanf("%d%d%d%d",&x,&y,&a,&b); 91 add(x,y,b-a);add(y,x,0); 92 B[x]+=a; 93 B[y]-=a; 94 low[i]=a; 95 } 96 int sum=0,st=n+1,en=n+2; 97 for(int i=1;i<=n;i++) 98 { 99 if(B[i]>0){ 100 sum+=B[i]; 101 add(i,en,B[i]); 102 add(en,i,0); 103 } 104 else if(B[i]<0){ 105 add(st,i,-B[i]); 106 add(i,st,0); 107 } 108 } 109 if(dinic(st,en)==sum) 110 { 111 printf("YES\n"); 112 for(int i=1;i<=m;i++) 113 printf("%d\n",e[i*2].cup-e[i*2].flow+low[i]); 114 } 115 else printf("NO"); 116 return 0; 117 }
有原有汇最大流
# include<iostream> # include<cstdio> # include<algorithm> # include<cstring> # include<cmath> # include<queue> using namespace std; const int mn = 220; const int inf = 0x3f3f3f3f; struct edge{int to,next,flow,cup;}; edge e[100005]; int head[mn],edge_max=1; void add(int x,int y,int z) { //printf("%d %d %d\n",x,y,z); e[++edge_max].to=y; e[edge_max].flow=e[edge_max].cup=z; e[edge_max].next=head[x]; head[x]=edge_max; } int n,m,s,t; int dfn[mn],cur[mn],deep[mn]; queue<int> q; bool bfs(int x,int y) { memset(deep,0,sizeof(deep)); q.push(x); deep[x]=1; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i;i=e[i].next) { if(e[i].flow>0 && deep[e[i].to]==0) { deep[e[i].to]=deep[u]+1; q.push(e[i].to); } } } return deep[y]!=0; } int dfs(int x,int dist,int y) { if(x==y) return dist; for(int &i=cur[x];i;i=e[i].next) { if(deep[e[i].to]==deep[x]+1 && e[i].flow!=0) { int di=dfs(e[i].to,min(dist,e[i].flow),y); if(di>0) { e[i].flow-=di; e[i^1].flow+=di; return di; } } } return 0; } int dinic(int x,int y) { int ret=0; while(bfs(x,y)) { for(int i=1;i<=n+2;i++) cur[i]=head[i]; while(int k=dfs(x,inf,y)) ret+=k; //printf("%d\n",ret); } //printf("%d\n",ret); return ret; } int main() { int x,y,a,b; scanf("%d%d%d%d",&n,&m,&s,&t); int st=n+1,en=n+2; for(int i=1;i<=m;i++) { scanf("%d%d%d%d",&x,&y,&a,&b); add(x,y,b-a);add(y,x,0); dfn[x]+=a,dfn[y]-=a; } /*for(int i=1;i<=n;i++) printf("%d ",dfn[i]); printf("\n");*/ for(int i=1;i<=n;i++) { if(dfn[i]>0) { add(i,en,dfn[i]); add(en,i,0); } else if(dfn[i]<0) { add(st,i,-dfn[i]); add(i,st,0); } } add(t,s,inf); add(s,t,0); int tmp=edge_max-1; dinic(st,en); for(int i=head[st];i;i=e[i].next) { if(e[i].flow!=0){ //printf("%d %d\n",e[i].to,e[i].flow); printf("please go home to sleep"); return 0; } } head[t]=e[head[t]].next; head[s]=e[head[s]].next; int ans=dinic(s,t); //printf("%d\n",ans); ans+=e[tmp].cup-e[tmp].flow; printf("%d\n",ans); return 0; }
有源有汇最小流
# include<iostream> # include<cstdio> # include<cmath> # include<cstring> # include<algorithm> # include<queue> using namespace std; typedef long long LL; const int mn = 50010; const LL inf = 0x3f3f3f3f3f3f3f; struct edge{ int to,next; LL flow,cup; }; edge e[125003*10]; int head[mn],edge_max=1; void add(int x,int y,LL z) { e[++edge_max].to=y; e[edge_max].flow=e[edge_max].cup=z; e[edge_max].next=head[x]; head[x]=edge_max; } int n,m,s,t; LL dfn[mn]; int deep[mn],cur[mn]; queue<int> q; bool bfs(int x,int y) { memset(deep,0,sizeof(deep)); q.push(x); deep[x]=1; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i;i=e[i].next) { if(deep[e[i].to]==0 && e[i].flow>0) { deep[e[i].to]=deep[u]+1; q.push(e[i].to); } } } return deep[y]!=0; } LL dfs(int x,LL dist,int y) { if(x==y) return dist; for(int &i=cur[x];i;i=e[i].next) { if(deep[e[i].to]==deep[x]+1 && e[i].flow!=0) { LL di=dfs(e[i].to,min(dist,e[i].flow),y); if(di>0) { e[i].flow-=di; e[i^1].flow+=di; return di; } } } return 0; } LL dinic(int x,int y) { LL ret=0; while(bfs(x,y)) { for(int i=1;i<=n+2;i++) cur[i]=head[i]; while(LL k=dfs(x,inf,y)) ret+=k; } return ret; } int main() { int x,y; LL a,b; scanf("%d%d%d%d",&n,&m,&s,&t); for(int i=1;i<=m;i++) { scanf("%d%d%lld%lld",&x,&y,&a,&b); add(x,y,b-a),add(y,x,0); dfn[x]+=a,dfn[y]-=a; } int st=n+1,en=n+2; LL sum=0; for(int i=1;i<=n;i++) { if(dfn[i]>0) { add(i,en,dfn[i]); add(en,i,0); sum+=dfn[i]; } else if(dfn[i]<0) { add(st,i,-dfn[i]); add(i,st,0); } } add(t,s,inf); add(s,t,0); int tmp=edge_max-1; if(sum!=dinic(st,en)) { printf("please go home to sleep"); return 0; } else { LL ans=e[tmp].cup-e[tmp].flow; head[s]=e[head[s]].next; head[t]=e[head[t]].next; ans-=dinic(t,s); printf("%lld\n",ans); } return 0; }