标签:技术 cap eof 网络最大流 去除 style 最大流 nbsp 技术分享
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 }
标签:技术 cap eof 网络最大流 去除 style 最大流 nbsp 技术分享
原文地址:http://www.cnblogs.com/hongyj/p/7010016.html