当前位置: 代码迷 >> 综合 >> poj-3436-记录路径的最大流-edmondskarp
  详细解决方案

poj-3436-记录路径的最大流-edmondskarp

热度:19   发布时间:2023-12-19 11:31:03.0

上午终于把最大流搞懂了,下午独立的做了一道题目,这道题目牵扯到如何记录最大流流过的路径问题。

想了好久,然后有好好的探索了一下edmondskarp算法的核心思想,发现每次的增光路都可以作为条通径。

这样的话就简单了,每次添加增光路的时候,用另一个数组记录一下增光路的添加路线,到后来用的时候,

再依次从数组中取出增光路的添加路线。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<stack>
#define min(a,b) (a<b?a:b)
using namespace std;
struct list
{int flow;int cow;
}map[101][101];
int len;
int shu[101][25];
int jiazhi[51][51][51];//增光路的添加记录,jiazhi[x][y][0]的值代表着这条边被增广了几次//jiazhi[x][y][z]的值代表着,第z次增广x-y边,增广的幅度
int sumber;
int sp,fp,n;
int prv[101];
int maxflow;
int bfs(int st,int end)
{int a[101],i;stack<int>q;memset(prv,-1,sizeof(prv));memset(a,0,sizeof(a));a[st]=100000;q.push(st);while(!q.empty()){int v;v=q.top();q.pop();for(i=0;i<n;i++){if(!a[i]&&map[v][i].cow>map[v][i].flow){q.push(i);prv[i]=v;a[i]=min(a[v],map[v][i].cow-map[v][i].flow);}}if(v==end)return a[end];}return 0;
}
void edmondskarp()
{int i,tmp;maxflow=0;sumber=0;memset(jiazhi,0,sizeof(jiazhi));while(tmp=bfs(sp,fp)){for(i=fp;i!=sp;i=prv[i]){map[prv[i]][i].flow+=tmp;map[i][prv[i]].flow-=tmp;int xx=prv[i];int yy=i;if(xx!=sp&&yy!=fp&&(xx/2!=yy/2))sumber++;jiazhi[xx][yy][++jiazhi[xx][yy][0]]=tmp;}maxflow+=tmp;}
}
int bijiao(int x,int y)
{int i;for(i=1;i<=len;i++){if((shu[x][i]+shu[y][i])==1)break;}if(i==len+1)return 1;else return 0;
}
void from(int x,int y,int z)
{int i;if(y==fp)return ;else{for(i=0;i<n;i++){if(jiazhi[y][i][jiazhi[y][i][0]]==z){if(y/2!=i/2&&i!=fp){printf("%d %d %d\n",(y/2+1),(i/2+1),z);}jiazhi[y][i][0]--;from(y,i,z);}}}
}
void print(int num,int f)
{int i;for(i=0;i<num;i++){if(jiazhi[sp][i][0]!=0){from(sp,i,jiazhi[sp][i][jiazhi[sp][i][0]]);//顺着最上面的增广路线往下找jiazhi[sp][i][0]--;i--;}}
}
int main()
{int p,i,j;while(scanf("%d%d",&p,&n)!=EOF){sp=n*2;fp=n*2+1;len=p;memset(map,0,sizeof(map));for(i=0;i<n;i++){cin>>shu[i*2][0];shu[i*2+1][0]=shu[i*2][0];int leap=0;for(j=1;j<=p;j++){cin>>shu[i*2][j];if(shu[i*2][j]==1)leap=1;}if(leap==0){map[sp][i*2].cow=shu[i*2][0];}leap=0;for(j=1;j<=p;j++){cin>>shu[i*2+1][j];leap+=shu[i*2+1][j];}if(leap==p){map[i*2+1][fp].cow=shu[i*2+1][0];}}for(i=0;i<n;i++){map[i*2][i*2+1].cow=shu[i*2][0];}for(i=0;i<n;i++){for(j=0;j<n;j++){if(i!=j&&bijiao(i*2+1,j*2)){map[i*2+1][j*2].cow=min(shu[i*2+1][0],shu[j*2][0]);}}}n=n*2+2;edmondskarp();printf("%d %d\n",maxflow,sumber);print(n,maxflow);}return 0;
}