• 求全局最小割(SW算法)


    hdu3002

    King of Destruction

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 1022    Accepted Submission(s): 400


    Problem Description
    Zhou xingxing is the successor of one style of kung fu called "Karate Kid".he is falling love with a beautiful judo student,after being humiliated by her boyfriend,a Taekwando master from Japan,Zhou is going to fight with his rival in love.The way they fight is to destroy the wooden plank between some wooden pegs,in order to cut these wooden pegs into two disconnected parts,and destroy each piece of plank need consume different energy.However Zhou xingxing is beginner after all,so he is turn to you for help,please calculate the minimum energy he need to destroy the wooden plank.
     

    Input
    The input consists of multiple test cases.
    Each test case starts with two integers n (0 < n <= 100) and m in one line, where n、m are the number of wooden pegs and wooden plank. 
    Following are m lines, each line contains three integers s, e and q (0 <= s, e < n,q > 0), meaning that there need q energy to destroy the wooden plank between s and e.
     

    Output
    There is only one line for each test case, which contains the minimum energy they need to complete this fight.
     

    Sample Input
    2 1 0 1 50 3 2 0 1 50 1 2 10
     

    Sample Output
    50 10

    题意:求无向图的最小割。
    思路:无向图的最小割又叫全局最小割,枚举汇点求最大流效率很低,因而普遍使用StoerWagner算法,时间复杂度为O(n^3)。
    程序:
    #include"stdio.h"
    #include"string.h"
    #define inf 99999999
    int G[666][666],ans;
    int min(int a,int b)
    {
        return a<b?a:b;
    }
    int f[666];
    int finde(int x)
    {
        if(x!=f[x])
            f[x]=finde(f[x]);
        return f[x];
    }
    void make(int a,int b)
    {
        int x=finde(a);
        int y=finde(b);
        if(x!=y)
            f[x]=y;
    }
    void Mincut(int n)
    {
        ans=inf;
        int node[666],dis[666];
        bool use[666];
        int i,k,pre;
        for(i=0;i<n;i++)
            node[i]=i;
        while(n>1)
        {
            int maxj=1;
            for(i=1;i<n;i++)//初始化到已圈集合的割大小
            {
                dis[node[i]]=G[node[i]][node[0]];
                if(dis[node[maxj]]<dis[node[i]])
                {
                    maxj=i;
                }
            }
            pre=0;
            memset(use,false,sizeof(use));
            use[node[0]]=true;
            for(k=1;k<n;k++)
            {
                if(k==n-1)//只剩最后一个没加入集合的点,更新最小割
                {
                    ans=min(ans,dis[node[maxj]]);
                    for(i=0;i<n;i++)//合并最后一个点以及推出它的集合中的点
                    {
                        G[node[i]][node[pre]]=G[node[pre]][node[i]]+=G[node[i]][node[maxj]];
                    }
                    node[maxj]=node[--n];//缩点后的图
                }
                use[node[maxj]]=true;
                pre=maxj;
                maxj=-1;
                for(i=1;i<n;i++)
                {
                    if(!use[node[i]])
                    {
                        dis[node[i]]+=G[node[i]][node[pre]];//将上次求的maxj加入集合,合并与它相邻的边到割集
                        if(maxj==-1||dis[node[maxj]]<dis[node[i]])
                            maxj=i;
                    }
                }
            }
        }
    }
    int main()
    {
        int n,m,i;
        while(scanf("%d%d",&n,&m)!=-1)
        {
            memset(G,0,sizeof(G));
            for(i=0;i<n;i++)
            {
                f[i]=i;
            }
            while(m--)
            {
                int a,b,c;
                scanf("%d%d%d",&a,&b,&c);
                G[a][b]=G[b][a]+=c;
                make(a,b);
            }
            int flag=0;
            for(i=0;i<n;i++)
            {
                if(finde(i)!=finde(0))
                    flag++;
            }
            if(flag)
                printf("0
    ");
            else
            {
                Mincut(n);
                printf("%d
    ",ans);
            }
    
        }
    }
    



  • 相关阅读:
    【Oracle/PLSQL】没事玩一个简单的表充值程序
    findmnt命令查找已挂载的文件系统
    如何让shell脚本变成可执行文件
    在Linux中如何查看文件的修改日期
    Dutree – Linux上的命令行磁盘使用情况分析工具
    用FRP做内网穿透使用远程桌面连接家里的windows电脑
    Dog-用于DNS查询的命令行工具
    【DeFi】一文读懂预言机原理、类型、现状和发展方向
    Vitalik Buterin 解读 Nathan Schneider 论文:加密经济治理的局限与改进思路
    Vitalik:回顾区块链近 5 年经济学进展,以及新出现的问题
  • 原文地址:https://www.cnblogs.com/mypsq/p/4348236.html
Copyright © 2020-2023  润新知