hdu3691(无向图最小割的求解)

来源:互联网 发布:linux启动ssh服务 编辑:程序博客网 时间:2024/05/21 09:44

题意:

给出一个无向图的源点和每个边的容量,让你自己选择汇点,使得最大流最小,输出最大流。


思路:

用SW算法求一遍无向图的最小割即可,源点如果在S集合中,我们只要在T集合中随便找一个点当作汇点就可以得到想要的最大流,反之亦然。


代码:

#include<cstdio>#include<cstring>#include<iostream>#include<cstring>#include<cstdlib>#include<cmath>#include<string>#include<queue>#include<vector>#include<map>#include<stack>#include<climits>#include<sstream>#include<algorithm>using namespace std;const int maxn=500;int ww[maxn][maxn];struct SW{int n,g[maxn][maxn],b[maxn],dist[maxn];void init(int nn,int w[maxn][maxn]){int i,j;n=nn;for(i=1;i<=n;i++)for(j=1;j<=n;j++)g[i][j]=w[i][j];}int Min_Cut_Phase(int ph,int &x,int &y){int i,j,t;b[t=1]=ph;for(i=1;i<=n;i++)if(b[i]!=ph)dist[i]=g[1][i];for(i=1;i<n;i++){x=t;for(t=0,j=1;j<=n;j++)if(b[j]!=ph&&(!t||dist[j]>dist[t]))t=j;b[t]=ph;for(j=1;j<=n;j++)if(b[j]!=ph)dist[j]+=g[t][j];}return y=t,dist[t];}void Merge(int x,int y){int i;if(x>y)swap(x,y);for(i=1;i<=n;i++)if(i!=x&&i!=y)g[i][x]+=g[i][y],g[x][i]+=g[i][y];if(y==n)return ;for(i=1;i<n;i++)if(i!=y){swap(g[i][y],g[i][n]);swap(g[y][i],g[n][i]);}}int Min_Cut(){int i,ret=0x3fffffff,x,y;memset(b,0,sizeof b);for(i=1;n>1;++i,--n){ret=min(ret,Min_Cut_Phase(i,x,y));Merge(x,y);}return ret;}};int main(){int n,m,src;while(scanf("%d%d%d",&n,&m,&src)!=EOF){if(!n&&!m&&!src)return 0;SW t;memset(ww,0,sizeof ww);for(int i=1;i<=m;i++){int u,v,x;scanf("%d%d%d",&u,&v,&x);ww[u][v]+=x;ww[v][u]+=x;}t.init(n,ww);printf("%d\n",t.Min_Cut());}return 0;}


0 0
原创粉丝点击