POJ 1273
给出M条边,N个点,求源点1到汇点N的最大流量。
本文主要就是附上dinic的模板,供以后参考。
#include <iostream> #include <stdio.h> #include <algorithm> #include <queue> #include <string.h> /* POJ 1273 dinic算法模板 边是有向的,而且存在重边,且这里重边不是取MAX,而是累加和 */ using namespace std; const int INF=0x3f3f3f3f; const int maxn=201; int pri[maxn]; long long sum; //计算总流量 int s,t; //s:源点 t:汇点 int n,m; struct Edge{ int c,f; }maps[maxn][maxn]; int min(int a,int b){ return a<b?a:b; } //每次先BFS,看看是否存在从源点到汇点的增广路 bool BFS() { queue<int> q; memset(pri,0,sizeof(pri)); pri[1]=1; q.push(1); while(!q.empty()) { int temp=q.front(); q.pop(); for(int i=1; i<=m; i++) { if(!pri[i] && maps[temp][i].c-maps[temp][i].f){ pri[i]=pri[temp]+1; if(i==t) return true; //即如果可以流到汇点,直接return true q.push(i); } } } //if(pri[m]>0) // return true; return false; } //p表示当前节点,flow表示该节点通过的流量 int dinic(int p,int flow){ if(p==t){ return flow; } int f=flow; //int value=0; for(int i=1;i<=m;i++){ if(pri[i]==pri[p]+1 && maps[p][i].c-maps[p][i].f){ int a=maps[p][i].c-maps[p][i].f; //a为该边可以增加的流量 int ff=dinic(i,min(a,flow)); //ff为路径中所有a的最小值,即为该条路中可以增加的流量 maps[p][i].f+=ff; //正向边 maps[i][p].f-=ff; //逆向边 //value+=ff; flow-=ff; if(flow<=0) break; //优化剪枝 } } //return value; if(f-flow<=0) pri[p]=0;//如果从p点流出去的流量<=0,那么设置pri[p]的值为0,之后在dinic中就不考虑到p点的情况了。 return f-flow; } void init(){ for(int i=1;i<=m;i++){ for(int j=1;j<=m;j++){ maps[i][j].c=maps[i][j].f=0; } } } int main() { int a,b,c; s=1; while(scanf("%d%d",&n,&m)!=EOF){ init(); //memset(maps,0,sizeof(maps)); sum=0; t=m; for(int i=1;i<=n;i++){ scanf("%d%d%d",&a,&b,&c); maps[a][b].c+=c; //该题有重边,这里要+=,不是去max } while(BFS()){ sum+=dinic(s,INF); } printf("%I64d\n",sum); } return 0; }