网络流主要解决三种问题:最大流、最小流和费用流。
最大流算法主要有三种:EK算法、Dinic算法、SAP算法
本篇博客是关于Dinic算法的。最坏的情况下,Dinic算法将达到复杂度O(V2E)。
1 #include<string.h> 2 #include<cstdio> 3 #include<algorithm> 4 #include<limits.h> 5 #include<queue> 6 using namespace std; 7 const int M=420; 8 const int inf=0x3f3f3f3f; 9 struct aa 10 { 11 int u,v,r,next; 12 } edge[888888]; 13 int cnt,dis[M],s,f,n,m,cost[M],pre[M],head[M]; 14 void add(int u,int v,int r) 15 { 16 edge[cnt].v=v; 17 edge[cnt].u=u; 18 edge[cnt].r=r; 19 edge[cnt].next=pre[u]; 20 pre[u]=cnt++; 21 edge[cnt].v=u; 22 edge[cnt].u=v; 23 edge[cnt].r=0; 24 edge[cnt].next=pre[v]; 25 pre[v]=cnt++; 26 } 27 bool bfs()//建立层次图 28 { 29 30 memset(dis,0,sizeof(dis)); 31 dis[s]=1; 32 queue<int>que; 33 que.push(s); 34 while(!que.empty()) 35 { 36 int u=que.front(); 37 que.pop(); 38 for(int i=pre[u]; i!=-1; i=edge[i].next) 39 { 40 int v=edge[i].v; 41 int r=edge[i].r; 42 if(dis[v]==0&&r>0) 43 { 44 dis[v]=dis[u]+1; 45 que.push(v); 46 } 47 } 48 } 49 return dis[f]>=1; 50 } 51 int dfs(int now,int Min)//多路增广 52 { 53 int a; 54 if(now==f) 55 return Min; 56 int cost=0; 57 for(int &i=head[now]; i!=-1; i=edge[i].next) 58 { 59 int v=edge[i].v; 60 int r=edge[i].r; 61 if(dis[v]==dis[now]+1&&r>0 &&(a=dfs(v,min(Min-cost,r)))) 62 { 63 edge[i].r-=a; 64 edge[i^1].r+=a; 65 cost+=a;//汇聚各个方向的流量 66 if(Min==cost)//当某几个方向的流量相加等于当前最大流量的时候就无法对别的路进行增广了 67 break; 68 } 69 } 70 return cost;//返回当前汇聚的流量 71 } 72 int Max_f() 73 { 74 int sum=0; 75 while(bfs()) 76 { 77 for(int i=0; i<=2*n; i++)//当前弧优化 78 head[i]=pre[i]; 79 while(int temp=dfs(s,inf))//一次bfs多次增广 80 sum+=temp; 81 } 82 return sum; 83 } 84 int main() 85 { 86 while(scanf("%d%d",&n,&m)!=EOF) 87 { 88 scanf("%d%d",&s,&f); 89 memset(pre,-1,sizeof(pre)); 90 f=f+n; 91 cnt=0; 92 for(int i=1; i<=n; i++) 93 { 94 scanf("%d",&cost[i]); 95 add(i,n+i,cost[i]); 96 } 97 while(m--) 98 { 99 int u,v; 100 scanf("%d%d",&u,&v); 101 add(n+u,v,inf); 102 add(v+n,u,inf); 103 } 104 int ans=Max_f(); 105 printf("%d\n",ans); 106 } 107 }