网络流相关模板及结论
一、一些结论
1、最大流最小割定理(Maximum Flow, Minimum Cut Theorem):网络的最大流等于最小割
2、任意一个流都小于等于任意一个割(废话)
3、(hdu 6214)最小割的割边一定满流,但是满流的边不一定是最小割的割边。(割边必满流,满流不一定是割边)
4、拆点:目的是让,每个点通过的流量为1。
对于一个网络流图G=(V,E),其中有源点s和汇点t,那么下面三个条件是等价的: 1. 流f是图G的最大流 2. 残留网络Gf不存在增广路 3. 对于G的某一个割(S,T),此时f = C(S,T)
二、模板
1、Dinic(多路增广+当前弧优化)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MAXN=1e4+3,MAXM=1e5+3,INF=0x7fffffff; 4 struct ppp{ 5 int from,to,flow,next; 6 }edge[MAXM<<1]; 7 int head[MAXN],tot,n,m,s,t,maxflow,vis; 8 int dep[MAXN],vztd[MAXN],cur[MAXN];//cur µ±Ç°»¡ 9 void add(int u,int v,int w) 10 { 11 edge[tot]=(ppp){u,v,w,head[u]}; 12 head[u]=tot; 13 tot++; 14 } 15 bool bfs() 16 { 17 for(int i=1;i<=n;i++) 18 cur[i]=head[i],dep[i]=0x3f3f3f3f,vztd[i]=0; 19 dep[s]=0; 20 queue<int>q; 21 q.push(s); 22 while(!q.empty()) 23 { 24 int k=q.front(); 25 q.pop(); 26 vztd[k]=0; 27 for(int i=head[k];i!=-1;i=edge[i].next) 28 { 29 int d=edge[i].to,lef=edge[i].flow; 30 if(dep[d]>dep[k]+1 and lef) 31 { 32 dep[d]=dep[k]+1; 33 if(!vztd[d]) 34 { 35 q.push(d); 36 vztd[d]=1; 37 } 38 } 39 } 40 } 41 if(dep[t]!=0x3f3f3f3f) return 1; 42 return 0; 43 } 44 int dfs(int u,int flow) 45 { 46 if(u==t) 47 { 48 // vis=1; 49 maxflow+=flow; 50 return flow; 51 } 52 int used=0; 53 for(int i=cur[u];i!=-1;i=edge[i].next) 54 { 55 cur[u]=i; 56 int d=edge[i].to; 57 int lef=edge[i].flow; 58 if(lef and dep[d]==dep[u]+1) 59 { 60 int low=dfs(d,min(flow-used,lef)); 61 if(low) 62 { 63 used+=low; 64 edge[i].flow-=low; 65 edge[i^1].flow+=low; 66 if(used==flow) break; 67 } 68 } 69 } 70 return used; 71 } 72 int dinic() 73 { 74 while(bfs()) 75 dfs(s,INF); 76 return maxflow; 77 } 78 int main() 79 { 80 scanf("%d%d%d%d",&n,&m,&s,&t); 81 memset(head,-1,sizeof(head)); 82 for(int i=1;i<=m;i++) 83 { 84 int u,v,w; 85 scanf("%d%d%d",&u,&v,&w); 86 add(u,v,w); 87 add(v,u,0); 88 } 89 printf("%d",dinic()); 90 return 0; 91 }
2、ISAP(加了当前弧怎么还慢了20msQAQ)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MAX=1e4+3,MAXM=1e5+5,INF=0x7fffffff; 4 struct ppp{ 5 int to,next,flow; 6 }edge[MAXM<<1]; 7 int head[MAX],dep[MAX],gap[MAX],cur[MAX]; 8 int n,m,s,t,tot,maxflow=0; 9 void add(int u,int v,int w) 10 { 11 edge[tot]=(ppp){v,head[u],w}; 12 head[u]=tot; 13 tot++; 14 } 15 void bfs() 16 { 17 memset(dep,-1,sizeof(dep)); 18 memset(gap,0,sizeof(gap)); 19 dep[t]=0; 20 gap[0]=1; 21 queue<int>q; 22 q.push(t); 23 while(!q.empty()) 24 { 25 int u=q.front(); 26 q.pop(); 27 for(int i=head[u];i!=-1;i=edge[i].next) 28 { 29 int v=edge[i].to; 30 if(dep[v]!=-1) continue; 31 q.push(v); 32 dep[v]=dep[u]+1; 33 gap[dep[v]]++; 34 } 35 } 36 return ; 37 } 38 inline int dfs(int u,int flow) 39 { 40 if(u==t) 41 { 42 maxflow+=flow; 43 return flow; 44 } 45 int used=0; 46 for(int i=cur[u];i!=-1;i=edge[i].next) 47 { 48 cur[u]=i; 49 int v=edge[i].to; 50 if(edge[i].flow and dep[v]+1==dep[u]) 51 { 52 int low=dfs(v,min(flow-used,edge[i].flow)); 53 if(low) 54 { 55 edge[i].flow-=low; 56 edge[i^1].flow+=low; 57 used+=low; 58 } 59 if(used==flow) return used; 60 } 61 } 62 gap[dep[u]]--; 63 if(gap[dep[u]]==0) dep[s]=n+1; 64 dep[u]++; 65 gap[dep[u]]++; 66 return used; 67 } 68 int isap() 69 { 70 bfs(); 71 while(dep[s]<n) 72 { 73 memcpy(cur,head,sizeof(head)); 74 dfs(s,INF); 75 } 76 return maxflow; 77 } 78 int main() 79 { 80 scanf("%d%d%d%d",&n,&m,&s,&t); 81 memset(head,-1,sizeof(head)); 82 for(int i=1;i<=m;i++) 83 { 84 int u,v,w; 85 scanf("%d%d%d",&u,&v,&w); 86 add(u,v,w); 87 add(v,u,0); 88 } 89 printf("%d",isap()); 90 return 0; 91 }
3、HLPP
-