HDU 1532 (Dinic算法)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1532
题目大意:
就是由于下大雨的时候约翰的农场就会被雨水给淹没,无奈下约翰不得不修建水沟,而且是网络水沟,并且聪明的约翰还控制了水的流速,本题就是让你求出最大流速,无疑要运用到求最大流了。题中N为水沟数,M为水沟的顶点,接下来Si,Ei,Ci分别是水沟的起点,终点以及其容量。求源点1到终点M的最大流速。注意重边。
这是Dinic算法,该算法的效率很高,复杂度O(m*n^2)。
Dinic算法的实现有以下几个步骤:
1:初始化容量网络和网络流
2:构造残留网络和层次网络,若汇点不在层次网络中则算法结束 输出最大流
3:在层次网络中用一次DFS进行增广,DFS执行完毕,该阶段的增广也就完毕了。
4:转至步骤2
参考代码:
#include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; #define INF 0x7fffffff #define min(a,b) a<b?a:b int N,M; int level[205]; int Si,Ei,Ci; struct Dinic { int c; int f; }edge[205][205]; bool dinic_bfs()//构造层次网络 { queue<int> Q; memset(level,0,sizeof(level));//初始化顶点的层次 为0 Q.push(1); level[1]=1; int u,v; while(!Q.empty()) { u=Q.front(); Q.pop(); for(v=1;v<=M;v++) { if(!level[v]&&edge[u][v].c>edge[u][v].f)//即顶点未被访问过,顶点u,v,存在边 { level[v]=level[u]+1;//给顶点标记层次 Q.push(v); } } } return level[M]!=0;//若返回false表明 汇点不在层次网络中 } int dinic_dfs(int u,int cp)//进行增广 { int tmp=cp; int v,t; if(u==M) return cp; for(v=1;v<=M&&tmp;v++) { if(level[u]+1==level[v]) { if(edge[u][v].c>edge[u][v].f) { t=dinic_dfs(v,min(tmp,edge[u][v].c-edge[u][v].f)); edge[u][v].f+=t; edge[v][u].f-=t; tmp-=t; } } } return cp-tmp; } int dinic()//求出最大流 { int sum,tf; sum=tf=0; while(dinic_bfs()) { while(tf=dinic_dfs(1,INF)) { sum+=tf; } } return sum; } int main() { while(~scanf("%d%d",&N,&M)) { memset(edge,0,sizeof(edge)); while(N--) { scanf("%d%d%d",&Si,&Ei,&Ci); edge[Si][Ei].c+=Ci;//防止重边 } int S=dinic(); printf("%d\n",S); } return 0; }