网络流:最大流之Dinic算法

≯℡__Kan透↙ 提交于 2019-12-05 05:23:05

网络流主要解决三种问题:最大流、最小流和费用流。

最大流算法主要有三种: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 }

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!