您的位置:首页 > 其它

SOJ 3254 Windy和水星-水星交通

2010-12-24 18:50 441 查看
使n座城市间至少有两座不连通,又全是带权无向边,即求图的最小割,可以用Stoer-Wagner算法解决

代码:
#include<iostream>
using namespace std;
const int inf=1<<30;
const int MAX=510;
int g[MAX][MAX];
int MinCut(int n)
{
int dis[MAX],node[MAX],vis[MAX];//dis[i]表示第i点到A的距离,node[i]表示i号节点属于哪个点
int i,j,k,prev,maxj,ans=inf,m=n;
for(i=0;i<n;i++)
{
node[i]=i;
}
while(n>1)
{
maxj=1;
for(i=0;i<n;i++)
{
dis[node[i]]=g[node[0]][node[i]];//初始化A(node[0])与各点的距离,即W(A,p)
if(dis[node[i]]>dis[node[maxj]])//选出第二个加入A的点
maxj=i;
}
prev=0;//第一个加入的点是0号点
memset(vis,0,sizeof(vis));
vis[node[0]]=1;
for(i=1;i<n;i++)
{
if(i==n-1)//A=V
{
ans=min(ans,dis[node[maxj]]);
for(k=0;k<n;k++)//将prev和maxj两个点缩为一个点 ,prev
{
g[node[k]][node[prev]]=(g[node[prev]][node[k]]+=g[node[k]][node[maxj]]);
}
node[maxj]=node[--n];//由于进入下一个循环后,当前的不会被涉及,所以将它所代表的集合
//由maxj所在的集合 代替,正好也将maxj这个集合删除,因为已经并入prev代表的集合
}
vis[node[maxj]]=1;
prev=maxj;
maxj=-1;
for(j=1;j<n;j++)//找点加入A,同时更新W(A,p) ,因为A新加入了节点prev
{
if(!vis[node[j]])
{
dis[node[j]]+=g[node[prev]][node[j]];
if(maxj==-1||dis[node[maxj]]<dis[node[j]])
maxj=j;
}
}
}
}
return ans;
}
int main()
{
int a,b,n,m,w;
while(scanf("%d",&n)!=EOF)
{
memset(g,0,sizeof(g));
for(a=0;a<n;a++)
{
for(b=0;b<n;b++)
{
scanf("%d",&g[a][b]);
}
}
printf("%d/n",MinCut(n));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: