zoukankan      html  css  js  c++  java
  • 次小生成树 (附:poj1679)

    次小生成树:

     

    在求最小生成树时,用数组path[i][j]来表示MST中i到j最大边权。

    求完后,直接枚举所有不在MST中的边,把它加入到MST中构成一棵新的树,且该树有环,此环是由刚加入的边(I,j)造成的,所以可以通过删除path[i][j]即可得到新的一颗树,且所有的该类树中必有一棵为次小生成树。

    比如如图所示:

    G,H不是MST上的边,通过加入边(G,H),得到一个环(B,H,G),然后由于在计算最小生成树时已经计算出G,H之间最大边权为path[G][H] = BH,所以通过删除BH即可得到一棵此时最小的生成树,然后更新答案即可

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    
    using namespace std;
    
    const int X = 105;
    const int INF = 100000000;
    
    int map[X][X],dis[X];
    int path[X][X];///记录i,j路径上的最大边权
    int pre[X];///前驱顶点
    int n;  ///顶点数
    bool use[X],in[X][X];
    
    int prim()
    {
        memset(use,false,sizeof(use));
        memset(pre,0,sizeof(pre));
        memset(in,false,sizeof(in));
    
        for(int i=0;i<=n;i++)
            dis[i] = INF;
        dis[1] = 0;
        int ans = 0;
    
        int MIN,k,p;
        for(int i=0;i<n;i++)
        {
            MIN = INF;
            for(int j=1;j<=n;j++)
                if(!use[j]&&MIN>dis[j])
                    MIN = dis[k = j];
            if(MIN==INF)
                return INF;
    
            p = pre[k];
            in[p][k] = in[k][p] = true;
            path[p][k] = path[k][p] = MIN;//由于还没有算过顶点k,所以直接等于MIN
    
            for(int j=1;j<=n;j++)
                if(use[j])  //更新已经在MST中的顶点
                    path[j][k] = path[k][j] = max(path[j][k],path[p][k]);
    
            use[k] = true;
            ans += MIN;
    
            for(int j=1;j<=n;j++)
                if(!use[j]&&dis[j]>map[k][j])
                    dis[j] = map[k][j],pre[j] = k;
        }
        return ans;
    }
    
    int main()
    {
        //freopen("sum.in","r",stdin);
        //freopen("sum.out","w",stdout);
        int t,m,x,y,z;
        cin>>t;
        while(t--)
        {
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    map[i][j] = map[j][i] = INF;
            while(m--)
            {
                scanf("%d%d%d",&x,&y,&z);
                map[x][y] = map[y][x] = z;
            }
            int ans = prim();
            int ok = true;
            for(int i=1;i<=n&&ok;i++)    //枚举找到不在MST上的边
                for(int j=1;j<=n&&ok;j++)
                    if(map[i][j]!=INF&&!in[i][j])
                        if(ans==ans-path[i][j]+map[i][j])
                            ok = false;
            if(ok)
                printf("%d\n",ans);
            else
                printf("Not Unique!\n");
        }
        return 0;
    }
  • 相关阅读:
    iOS本机生成证书请求文件流程
    NET开发必备工具之-LINQPad
    css3 地球自转公转
    css3 里外转 动画
    css动画,三片扇叶旋转
    max-height、min-height、height优先级的问题
    前端实现在线预览pdf、word、xls、ppt等文件
    原生js实现上传下载
    js通过拍照或相册选择图片后,做压缩处理
    原生js 手机端 调用 拍照、录像、录音、相册(含图片或视频)、音频文件等
  • 原文地址:https://www.cnblogs.com/yejinru/p/2554070.html
Copyright © 2011-2022 走看看