【网络流】——搞搞dinic

只是搞一搞而已。

https://www.luogu.org/problem/P3376网络流最大流板子。

程序部分参考自大大的题解。

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,但是懒,鸽着吧。

猜你喜欢

转载自www.cnblogs.com/Nelson992770019/p/11285448.html