zoukankan      html  css  js  c++  java
  • 次小生成树

    次小生成树,顾名思义,求最小生成树之外的最小生成树,即倒数第二小的生成树。

    先利用prim求出最小生成树。并将最小生成树任意两点之间路径当中的权值最大的那一条找出来,为什么要找最大的呢,因为生成树再加入一条边之后一定构成了回路,那么肯定要去掉这个回路当中一条边才是生成树,那么,怎么去边才是次小的,那就去掉除了刚刚添加的一条边之外回路当中权值最大的一个,所以留下的就是最小的。

    题目:POJ1679

    题意:给定图,让求它的最小生成树是否唯一。如果唯一的话输出最小生成树的权值和,否则输出Not Unique!

    #include <iostream>
    #include <stdio.h>
    #define MAX 0x3f3f3f3f
    const int N = 105;
    using namespace std;
    int mp[N][N],vis[N],dis[N],st[N],max1[N][N],pre[N];
    int n,m,ans;
    void Init(){
        for(int i = 0;i < N; i++)
            for(int j = 0; j < N; j++){
                mp[i][j] = mp[j][i] = MAX;
                max1[i][j] = max1[j][i] = 0;
            }
        fill(vis,vis+N,0);
    }
    void prim(){
        int min_value,top = 0,k;
        vis[1] = 1;
        ans = 0;
        for(int i = 1;i <= n; i++)
        {
            pre[i] = 1;
            dis[i] = mp[1][i];
        }
        dis[1] = 0;
        st[top++] = 1;//保存MST的结点
        for(int i = 1;i <= n; i++){
            min_value = MAX;
            for(int j = 1; j <= n; j++){
                if(!vis[j]&&min_value>dis[j])
                    min_value = dis[k = j];
            }
            if(min_value==MAX)
                    break;
            vis[k] = 1;
            ans += min_value;
            for(int j = 0;j < top; j++)
                max1[st[j]][k] = max1[k][st[j]] = max(min_value,max1[st[j]][pre[k]]);//新加入点到MST各点路径最大值
            st[top++] = k;//保存MST的结点
            for(int j = 1;j<=n;j++)
                if(!vis[j]&&dis[j]>mp[k][j])
                {
                    dis[j] = mp[k][j];
                    pre[j] = k;//记录直接前驱
                }
        }
    }
    int main()
    {
        int t;
        cin>>t;
        while(t--){
            Init();
            int s,e,value;
            cin>>n>>m;
            for(int i = 0;i < m;i++)
            {
                cin>>s>>e>>value;
                mp[s][e] = mp[e][s] = value;
            }
            prim();
            int minn = MAX;
            for(int i = 1; i <= n; i++)枚举MST以外的边
                for(int j = 1;j <= n; j++)
                    if(i!=j&&i!=pre[j]&&j!=pre[i])
                        minn = min(minn,mp[i][j]-max1[i][j]);
            if(minn)
                cout<< ans <<endl;
            else
                cout<< "Not Unique!"<<endl;
        }
        return 0;
    }
    宝剑锋从磨砺出 梅花香自苦寒来
  • 相关阅读:
    poj 1743 Musical Theme 后缀数组
    poj 1743 Musical Theme 后缀数组
    cf 432D Prefixes and Suffixes kmp
    cf 432D Prefixes and Suffixes kmp
    hdu Data Structure? 线段树
    关于position和anchorPoint之间的关系
    ios POST 信息
    CALayers的代码示例
    CALayers详解
    ios中得sqlite使用基础
  • 原文地址:https://www.cnblogs.com/GHzcx/p/8252400.html
Copyright © 2011-2022 走看看