POJ1273:Drainage Ditches——题解
http://poj.org/problem?id=1273
题目大意:
n点m边网络流,求1-n最大流。
——————————————
网络流板子,切了。
#include <cstdio> #include <iostream> #include <cmath> #include <cstring> #include <algorithm> using namespace std; const int maxn=201; const int INF=2147483640; inline int read(){ int X=0,w=0;char ch=0; while(ch<'0'||ch>'9'){w|=ch=='-';ch=getchar();} while(ch>='0'&&ch<='9')X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct node{ int next; int to; int w; }edge[2*maxn]; int head[2*maxn],cnt=-1; void add(int u,int v,int w){//u起点v终点w容量 cnt++; edge[cnt].to=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt; return; } int lev[maxn],cur[maxn];//lev层数,cur[i]为以i为起点的边的编号 bool bfs(int m){//强制1为源点,m为汇点 int dui[m],r=0;//队列和右指针 for(int i=1;i<=m;i++){//初始化 lev[i]=-1; cur[i]=head[i]; } dui[0]=1,lev[1]=0; int u,v;//u起点v终点 for(int l=0;l<=r;l++){//左指针 u=dui[l]; for(int e=head[u];e!=-1;e=edge[e].next){ v=edge[e].to; if(edge[e].w>0&&lev[v]==-1){//1.能走 2.未分层 lev[v]=lev[u]+1; r++; dui[r]=v;//v入队 if(v==m)return 1;//分层完毕 } } } return 0;//无法分层 } int dinic(int u,int flow,int m){//u当前点,flow为下面的点能够分配多大的流量,m终点 if(u==m)return flow;//终点直接全流入 int res=0,delta;//res实际流量 for(int &e=cur[u];e!=-1;e=edge[e].next){//'&'相当于cur[u]=e;即流满的边不会再被扫一次 int v=edge[e].to; if(edge[e].w>0&&lev[u]<lev[v]){//只能从低层往高层流 delta=dinic(v,min(edge[e].w,flow-res),m); if(delta>0){//如果增广 edge[e].w-=delta;//正向边容量减少 edge[e^1].w+=delta;//反向边仍量增加(暗示退流) res+=delta;//扩张流量增加 if(res==flow)break;//可流的都流完了,及时跳出 } } } if(res!=flow)lev[u]=-1;//没流完,说明以后不能从这个点流出任何流量,那就不需要这个点了 return res; } int main(){ int n,m; while(scanf("%d%d",&n,&m)!=EOF){ cnt=-1; memset(head,-1,sizeof(head)); for(int i=1;i<=n;i++){ int s=read(); int e=read(); int c=read(); add(s,e,c); add(e,s,0); } int ans=0; while(bfs(m)==1)ans+=dinic(1,INF,m); printf("%d\n",ans); } return 0; }