首页 > 代码库 > 【算法】网络最大流 Dinic
【算法】网络最大流 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));//等级都初始化为036 level[s]=1;//起点等级为一,那么如果没有增广路到终点,返回时将会返回false37 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,否则返回false53 }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
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。