Jungle Roads POJ - 1251 (最小生成树)

发布时间 2023-03-28 17:24:12作者: HelloHeBin

题意:有一个旅游区,旅游区有很多的景点,景点间需要开通缆车,使得任意两个景点可以互相到达。现在给出一些点间的缆车线路制造成本,两个景点之间可能有多重制造方式。问最少的花费是多少。

分析:连通+最少的花费 = 最小生成树。
Prim算法适用于稠密图, Kruskal适用于稀疏图

  • 好家伙,两个 runtime-error
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long LL;
const int N =210, INF = 0x3f3f3f3f;
int n, m, p, g[N][N];
struct T {
    int u, v, w;
    T(int a = 0, int b = 0, int c = 0) : u(a), v(b), w(c) {}
    bool operator<(const T& r) const { return w < r.w; }
} e[N*N];

int dis[N];
bool st[N];
int prim() {
    memset(dis, 0x3f, sizeof(dis));
    memset(st, 0, sizeof(st));
    int ans = 0;
    for (int i = 0; i < n; i++) {
        int u = -1;
        for (int j = 0; j < n; j++)
            if (!st[j] && (u == -1 || dis[u] > dis[j]))
                u = j;
        if (u && dis[u] == INF) return -1;
        if (u) ans += dis[u];
        for (int j = 0; j < n; j++)
            dis[j] = min(dis[j], g[u][j]);
        st[u] = 1;
    }
    return ans;
}

int f[N];
int find(int u) {
    return u == f[u] ? u : f[u] = find(f[u]);
}
int kruskal() {
    int ans = 0, cnt = 0;
    for (int i = 0; i <= n; i++)
        f[i] = i;
    sort(e + 1, e + 1 + p);
    for (int i = 1; i <= p; i++) {
        int fu = find(e[i].u), fv = find(e[i].v);
        if (fu != fv) f[fu] = f[fv], ans += e[i].w, cnt++;
        if (cnt == n - 1) break;
    }
    return cnt == n - 1 ? ans : -1;
}

int main() {
    char u, v;
    int w, t;
    while (~scanf("%d\n", &n) && n) {
        memset(g, 0x3f, sizeof(g));
        p = 0, t = n - 1;
        while (t--) {
            scanf("%c%d", &u, &m), u -= 'A';
            for (int i = 1; i <= m; i++) {
                scanf(" %c%d", &v, &w), v -= 'A';
                g[u][v] = g[v][u] = min(g[u][v], w);
                e[++p] = T(u, v, w);
            }
            getchar();  // \n
        }
        printf("%d\n", prim());
        // printf("%d\n", kruskal());
    }
    return 0;
}