BZOJ-3345: Pku2914 Minimum Cut

[文章目录]

Description

有一个n个点,m条边的无向图,求将这个图断成两个联通块需要删除的边的边权和最小值。n<=500 m<=10000

Stoer Wagner 算法,求图的全局最小割,时间复杂O(n^3)
就是维护一个集合,每次向里扔不在当前集合的点中与当前集合联通性最强的点,用最后一个点与当前集合之间的联通性更新答案,然后将后两个进入集合的点缩成一个点。再重复进行这个操作即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 510 
const int inf=0x3f3f3f3f;
int n,m,mp[N][N];
int Stoer_Wagner()
{
    static int f[N],z[N];
    static bool v[N],del[N];
    int re=inf,t,i,j,k,top;
    for(t=n;t>1;--t)
    {
        memset(f,0,sizeof f);
        memset(v,0,sizeof v);
        top=0,f[0]=-1;
        for(i=1;i<=t;++i)
        {
            for(k=0,j=1;j<=n;++j) if(!del[j]&&!v[j]&&f[j]>f[k]) k=j;
            z[++top]=k; v[k]=1;
            for(j=1;j<=n;++j) if(!del[j]&&!v[j]) f[j]+=mp[k][j];
        }
        re=min(re,f[z[top]]);
        for(i=1;i<=n;++i) if(!del[i])
        {
            if(i!=z[top]&&i!=z[top-1])
            {
                mp[z[top-1]][i]+=mp[z[top]][i];
                mp[i][z[top-1]]+=mp[i][z[top]];
            }
            mp[i][z[top]]=mp[z[top]][i]=0;
        }
        del[z[top]]=1;
    }
    return re;
}
int main()
{
    scanf("%d%d",&n,&m);
    int i,a,b,c;
    for(i=1;i<=m;++i)
    {
        scanf("%d%d%d",&a,&b,&c);
        mp[a][b]+=c; mp[b][a]+=c;
    }
    printf("%d",Stoer_Wagner());
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注