只是搞一搞而已。
https://www.luogu.org/problem/P3376网络流最大流板子。
程序大部分参考自A_Comme_Amour大大的题解。
Dinic:
1.从s跑一遍bfs来分层,如果能分到t层,请转至2。
2.跑dfs,求出当前的flow,加到答案中,欲知细节请到3。
3.dfs(u,t,lim)表示(当前点,汇点,路上最小弧),首先预判一下两种情况:(1.到汇点了,即u==t 2.最小弧为0,即lim==0,都可以直接return lim)
然后跑dfs:往哪个方向走?(往分层处,即新点深度是旧点+1,并且能走(f=dfs(v,t,min(lim,w)),即找增广路),这时候更新路径:原路-f,反向+f,flow+f,lim-f,判断一下lim如果小于等于0就不用再往下增广了。最后返回flow。
4.最后返回flow的和就好了。
5.可以选择弧优化,一点小细节,具体看程序:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 const int inf=1e9; 7 const int N=1e6+10; 8 int n,m,S,T,cnt=-1,maxflow,head[N],cur[N],deep[N]; 9 queue<int> q; 10 struct edge{ 11 int to,next,w; 12 }e[N*2]; 13 void addedge(int from,int to,int w){ 14 e[++cnt]=(edge){to,head[from],w}; 15 head[from]=cnt; 16 } 17 int bfs(int s,int t){//将图分层。 18 for(int i=1;i<=n;i++) deep[i]=1e9+10; 19 while(!q.empty()) q.pop(); 20 for(int i=1;i<=n;i++) cur[i]=head[i]; 21 deep[s]=0; 22 q.push(s); 23 while(!q.empty()){ 24 int u=q.front(); 25 q.pop(); 26 for(int i=head[u];i!=-1;i=e[i].next){ 27 int v=e[i].to; 28 if(deep[v]>inf&&e[i].w){ 29 deep[v]=deep[u]+1; 30 q.push(v); 31 } 32 } 33 } 34 if(deep[t]<inf) return true; 35 else return false; 36 } 37 int dfs(int u,int t,int lim){//lim=minedge(s->u) 38 if(!lim||u==t) return lim;//如果到了汇点或者边权为0则返回边权。 39 int flow=0,f; 40 for(int i=cur[u];i!=-1;i=e[i].next){ 41 cur[u]=i;//弧优化 42 int v=e[i].to; 43 if(deep[v]==deep[u]+1&&(f=dfs(v,t,min(lim,e[i].w)))){//如果这段能到达汇点并且服从分层 44 flow+=f; 45 lim-=f; 46 e[i].w-=f; 47 e[i^1].w+=f; 48 if(!lim) break; 49 } 50 } 51 return flow; 52 }//important 53 void dinic(int s,int t){ 54 while(bfs(s,t)){ 55 maxflow+=dfs(s,t,inf); 56 } 57 } 58 int main(){ 59 scanf("%d%d%d%d",&n,&m,&S,&T); 60 int x,y,z; 61 memset(head,-1,sizeof(head)); 62 for(int i=1;i<=m;i++){ 63 scanf("%d%d%d",&x,&y,&z); 64 addedge(x,y,z); 65 addedge(y,x,0); 66 } 67 dinic(S,T); 68 printf("%d",maxflow); 69 return 0; 70 }
本来想搞ISAP,但是懒,鸽着吧。
原文:https://www.cnblogs.com/Nelson992770019/p/11285448.html