2011.07.30

POJ  2914  Minimum Cut

        题意:果的求无向图最小割。n个点,m条边表示图,让输出最小割有几条边。

        套了前几天学的Store Wagner模板,加了注释,O(n^3)不算很快但通过无压力= =

#include<cstdio>
#include<fstream>
#include<cstring>
#define MAXV 600
using namespace std;
const int inf=1<<29;
int m,n,res,g[MAXV][MAXV];

void Mincut(int n)
{
    int link[MAXV],d[MAXV];          //link作合并后的指针用,d为距离
    bool vis[MAXV];                //vis访问标记
    int i,pre,j,k;
    for(i=0;i<n;i++) link[i]=i;      //指针初始化
    while(n>1){
        int maxj=1;
        for(i=1;i<n;i++){       //初始化到已圈集合的大小
            d[link[i]]=g[link[0]][link[i]];      //先把顶点0加入集合
            if(d[link[i]]>d[link[maxj]]) maxj=i;   //寻找最远点
        }
        pre=0;
        memset(vis,0,sizeof(vis));
        vis[link[0]]=true;
        for(i=1;i<n;i++){
            if(i==n-1){                //只剩下最后一个点没加入集合,更新最小割
                res=min(res,d[link[maxj]]);
                for(k=0;k<n;k++)             //合并最后一个节点和推出它的集合中的点
                    g[link[k]][link[pre]]=(g[link[pre]][link[k]]+=g[link[k]][link[maxj]]);
                link[maxj]=link[--n];         //缩点后的图
            }
            vis[link[maxj]]=true;
            pre=maxj;
            maxj=-1;
            for(j=1;j<n;j++)
                if(!vis[link[j]]){
                    d[link[j]]+=g[link[pre]][link[j]];        //将上次求的maxj加入集合,合并与它相邻的边到割集
                    if(maxj==-1 || d[link[maxj]]<d[link[j]])    //裸的prim
                        maxj=j;
            }
        }
    }
    return ;
}
int main()
{
    freopen("in","r",stdin);
    freopen("out","w",stdout);
    int u,w,v;
    while(scanf("%d%d",&n,&m)!=EOF){
        memset(g,0,sizeof(g));
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&u,&v,&w);
            g[u][v]+=w;
            g[v][u]+=w;
        }
        res=inf;
        Mincut(n);
        printf("%d\n",res);
    }
    return 0;
}


       


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值