zoukankan      html  css  js  c++  java
  • POJ 1679 The Unique MST(次小生成树)

    题意:

    给定一张无向图,如果存在唯一的一个最小生成树,则输出大小,如果不存在,则输出 Not Unique!

    思路:

    1. 求其最小生成树,对于树上的每 2 个节点 u, v,如果边 (u, v) 不在树上,则补全,成为一个环,然后删除这个环中除了 (u, v) 之外最大的边

    2. 如果此时树的大小仍为最小生成树的大小,则最小生成树不唯一。

    3. dp[i, j] 代表生成树上两个节点 (i, j) 之间,最大的边的值。此时利用到了动态规划的思想求解。

    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 110;
    const int INFS = 0x3FFFFFFF;
    
    int d[MAXN], p[MAXN], map[MAXN][MAXN], dp[MAXN][MAXN];
    bool vis[MAXN];
    
    int prim(int n) {
        int ans = 0;
    
        for (int i = 1; i <= n; i++)
            d[i] = map[1][i], p[i] = 1;
        memset(dp, 0, sizeof(dp));
        memset(vis, false, sizeof(vis));
    
        vector<int> inq;
        vis[1] = true; inq.push_back(1);
        for (int k = 1; k < n; k++) {
            int j, temp = INFS;
            for (int i = 1; i <= n; i++) {
                if (!vis[i] && d[i] < temp)
                    j = i, temp = d[i];
            }
            vis[j] = true; ans += temp;
    
            for (int i = 0; i < inq.size(); i++)
                dp[j][inq[i]] = dp[inq[i]][j] = max(temp, dp[inq[i]][p[j]]);
            inq.push_back(j);
    
            for (int i = 1; i <= n; i++) {
                if (!vis[i] && d[i] > map[i][j])
                    d[i] = map[i][j], p[i] = j;
            }
        }
        return ans;
    }
    
    int main() {
        int cases;
        scanf("%d", &cases);
        while (cases--) {
            int n, m;
            scanf("%d%d", &n, &m);
            for (int i = 1; i <= n; i++)
                for (int j = 1; j <= n; j++)
                    map[i][j] = (i == j) ? 0 : INFS;
            for (int i = 0; i < m; i++) {
                int a, b, c;
                scanf("%d%d%d", &a, &b, &c);
                map[a][b] = map[b][a] = c;
            }
            int ans = prim(n);
            int cflag = INFS;
            for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++)
                if (i != j && map[i][j] != INFS && p[i] != j && p[j] != i)
                    cflag = min(cflag, map[i][j] - dp[i][j]);
            if (cflag == 0) 
                printf("Not Unique!\n");
            else 
                printf("%d\n", ans);
        }
        return 0;
    }
    -------------------------------------------------------

    kedebug

    Department of Computer Science and Engineering,

    Shanghai Jiao Tong University

    E-mail: kedebug0@gmail.com

    GitHub: http://github.com/kedebug

    -------------------------------------------------------

  • 相关阅读:
    1697 ⑨要写信
    1220 数字三角形
    4979 数塔
    bzoj1618[Usaco2008 Nov]Buying Hay 购买干草
    bzoj1066[SCOI2007]蜥蜴
    bzoj1008[HNOI2008]越狱
    cf437D The Child and Zoo
    cf437C The Child and Toy
    cf437B The Child and Set
    cf437A The Child and Homework
  • 原文地址:https://www.cnblogs.com/kedebug/p/3049437.html
Copyright © 2011-2022 走看看