您的位置:首页 > 其它

Stoer-Wagner算法(O(n^3))求全局最小割 hdu3691 2010福州站B题

2011-08-15 16:25 489 查看
这题比赛时没有做出来,一直以来都没有想到是全局最小割,现在看了别人的解题报告。。。

题意:给一图,入口,求将哪个点设为出口,使得最大流最小

分析:一直没有看出来是最小割集,想到那了还是蛮好理解的。http://wenku.baidu.com/view/7545db0d76c66137ee0619bd.html

//求去掉最少的边使连通集划分为两连通集  就是用Stoer-Wagner算法(O(n^3))求最小的割集
#include<iostream>
using namespace std;

const int maxint=0x7fffffff;
const int maxn=510;
int g[maxn][maxn];
int StoerWagner(int n)
{
int i,j,k,s,t,p=n,min,cut=maxint,dist[maxn];
bool d[maxn],visit[maxn];

memset(d,false,sizeof(d));//表示是否已被合并
while(--p>0)
{
memset(visit,false,sizeof(visit));//是否已经加入S集合
memset(dist,0,sizeof(dist));//S外的元素与S里元素的权值和
i=0;
while(d[i]) i++;
visit[i]=true;
for(j=0;j<n;j++)
if(!d[j]&&!visit[j])
dist[j]=g[j][i];
t=i,s=i;
for(;i<n;i++)
{
for(min=0,k=i,j=0;j<n;j++)
if(!d[j]&&!visit[j]&&dist[j]>min)
min=dist[k=j];
if(!min) break;

visit[k]=true;
for(j=0;j<n;j++)
if(!d[j]&&!visit[j])
dist[j]+=g[j][k];
s=t;//上一个元素
t=k;//现在的元素
}
if(cut>dist[t]) cut=dist[t];
d[t]=true;
for(i=0;i<n;i++)
if(!d[i])
{
g[s][i]+=g[t][i];
g[i][s]+=g[i][t];
}
}
return cut;
}
bool BFS(int n)//时间没优化
{
int i,k,visit[maxn],head=0,tail=0,q[maxn];
memset(visit,false,sizeof(visit));
q[tail++]=0;
visit[0]=true;
while(head!=tail)
{
k=q[head++];
for(i=0;i<n;i++)
if(!visit[i]&&g[k][i])
{
visit[i]=true;
q[tail++]=i;
}
}
for(i=0;i<n;i++)
if(!visit[i])
return false;
return true;
}
int main()
{
int i,n,m,s,t,w;
while(scanf("%d%d%d",&n,&m,&s)!=EOF)
{
if(!n&&!m&&!s) break;
memset(g,0,sizeof(g));
for(i=0;i<m;i++)
{
scanf("%d%d%d",&s,&t,&w);
s--,t--;
g[s][t]+=w;
g[t][s]+=w;
}
printf("%d\n",StoerWagner(n));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: