Description
windy被请到了水星交通部,交通部长现在想知道水星的交通安全度为多少在水星上有n座城市,任意两座城市之间有一条权值在[1,10^5]的双向路定义:为了使得这n座城市至少有两座之间不连通,最少需要破坏的权值为安全度求水星的交通安全度
Input
输入包含多组测试数据,每组数据第一行有一个整数,n ( 2 <= n <= 100 )接下来n行,每行n个整数,除主对角线外,均为范围在[1,10^5]的整数,对角线上的权值保证为0,保证[i][j]=[j][i]
Output
每组数据输出一行,为水星的交通安全度
Sample Input
30 1 31 0 23 2 0
Sample Output
3
//
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 501;
const int MAXV = 0x3F3F3F3F;
int n,m,v[MAXN],mat[MAXN][MAXN],dis[MAXN];
bool vis[MAXN];
int res;
int Stoer_Wagner(int n) {
int res = MAXV;
for (int i = 0;i < n;i++)
v[i] = i;
while (n > 1) {
int maxp = 1,prev = 0;
for (int i = 1;i < n;i++) {//初始化到已圈集合的割大小
dis[v[i]] = mat[v[0]][v[i]];
if (dis[v[i]] > dis[v[maxp]])
maxp = i;
}
memset(vis,0,sizeof(vis));
vis[v[0]] = true;
for (int i = 1;i < n;i++) {
if (i == n - 1) { //只剩最后一个没加入集合的点,更新最小割
res = min(res,dis[v[maxp]]);
for (int j = 0; j < n; j++) { //合并最后一个点以及推出它的集合中的点
mat[v[prev]][v[j]] += mat[v[j]][v[maxp]];
mat[v[j]][v[prev]] = mat[v[prev]][v[j]];
}
v[maxp] = v[--n];//缩点后的图
}
vis[v[maxp]] = true;
prev = maxp;
maxp = -1;
for (int j = 1;j < n;j++)
if (!vis[v[j]]) { //将上次求的maxp加入集合,合并与它相邻的边到割集
dis[v[j]] += mat[v[prev]][v[j]];
if (maxp == -1 || dis[v[maxp]] < dis[v[j]])
maxp = j;
}
}
}
return res;
}
int main()
{
while (scanf("%d", &n) != EOF)
{
memset(mat,0,sizeof (mat));
int x,y,z;
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",&mat[i][j]);
}
}
printf("%d\n",Stoer_Wagner(n));
}
}