算法网络最大流 Dinic

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法网络最大流 Dinic相关的知识,希望对你有一定的参考价值。

 

Dinic的大体思路是和EK差不多的(其实很多算法的大体思路都一样),只不过Dinic在每次寻找增广路时先bfs一下,给每个点都加上一个等级,而规定:只有等级相邻的两个点之间才能走,那么在dfs时就会减掉很多无用因此不必要的道路

 

技术分享
 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<queue>
 6 using namespace std;
 7 const int inf=1000000000,MAXN=100000+10,MAXM=1000000+10;
 8 int to[MAXM],nex[MAXM],cap[MAXM],beg[MAXN],level[MAXN],n,m,s,t,e=1;//to,nex,cap与边有关,所以定MAXM,而beg,level与点有关,所以定MAXN,level用来分层,cap和flow两个数组缩减为一个cap,表示剩余的容量,节省空间
 9 inline void read(int &x)
10 {
11     x=0;
12     char c=getchar();
13     while(c<0||c>9)c=getchar();
14     while(c>=0&&c<=9)
15     {
16         x=(x<<3)+(x<<1)+(c^0);
17         c=getchar();
18     }
19 }
20 inline void insert(int x,int y,int z)//链式前向星加边
21 {
22     ++e;//e的初始值为1,因为后面将用到^(异或)
23     to[e]=y;
24     nex[e]=beg[x];
25     beg[x]=e;
26     cap[e]=z;
27     ++e;
28     to[e]=x;
29     nex[e]=beg[y];
30     beg[y]=e;
31     cap[e]=0;
32 }//网络流都是有向图,但要有反向弧,所以建两条,但反向的cap值初始化为0,因为正向没有流量时,反向是不能流的
33 inline bool bfs()//BFS分层
34 {
35     memset(level,0,sizeof(level));//等级都初始化为0
36     level[s]=1;//起点等级为一,那么如果没有增广路到终点,返回时将会返回false
37     queue<int> q;//定义BFS标准队列
38     q.push(s);//起点入队
39     while(!q.empty())//队列中还有未访问到的元素
40     {
41         int x=q.front();//去除队首元素
42         q.pop();//删除队首元素
43         for(register int i=beg[x];i;i=nex[i])//链式前向星标准循环
44         {
45             if(cap[i]&&!level[to[i]])//还有容量剩余并且该点未访问过
46             {
47                 level[to[i]]=level[x]+1;//赋等级
48                 q.push(to[i]);//该点加入队列
49             }
50         }
51     }
52     return level[t];//如果还存在一条起点到终点的增广路,则返回true,否则返回false
53 }
54 inline int dfs(int x,int maxflow)//相当于EK的路径返回和加流量,DFS实现,x表示当前位置(点),maxflow表示之前的剩余容量的最大值
55 {
56     if(!maxflow||x==t)return maxflow;//如果没有剩余了或已经到终点了,直接返回
57     int res=0;
58     for(register int i=beg[x];i;i=nex[i])
59     {
60         if(cap[i]&&level[to[i]]==level[x]+1)//还有容量,并且该点到原位置的等级正好相差1,即连通并可行
61         {
62             int f=dfs(to[i],min(maxflow,cap[i]));//继续走下去,并将剩余容量与这条边的容量进行比较,更新剩余容量,即寻找瓶颈
63             res+=f;//这条边上的最大流加上瓶颈
64             maxflow-=f;//剩余容量最大值减去瓶颈
65             cap[i]-=f;//该边剩余容量减去瓶颈
66             cap[i^1]+=f;//该边反向边容量加上瓶颈
67         }
68     }
69     return res;//返回
70 }
71 inline int Dinic()//Dinic求网络流最大流
72 {
73     int res=0;
74     while(bfs())res+=dfs(s,inf);//res加上每一条从起点到终点的增广路上的最大流
75     return res;
76 }
77 int main()
78 {
79     read(n);read(m);read(s);read(t);//s为起点,t为终点,n为点数,m为边数
80     for(register int i=1;i<=m;++i)
81     {
82         int x,y,z;
83         read(x);read(y);read(z);
84         insert(x,y,z);
85     }
86     printf("%d",Dinic());
87     return 0;
88 }
网络最大流 Dinic

 

以上是关于算法网络最大流 Dinic的主要内容,如果未能解决你的问题,请参考以下文章

网络流最大流入门(Dinic算法)模板

网络流Dinic(本篇介绍最大流)

网络流最大流之Dinic算法

网络流最大流——dinic算法

网络最大流 dinic算法

网络流最大流——Dinic算法