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;
}
posted @ 2013-04-28 15:36  kedebug  阅读(217)  评论(0编辑  收藏  举报