Agri-Net POJ - 1258 (最小生成树)
题意:有n个农场,已知这n个农场都互相相通,有一定的距离,现在每个农场需要装光纤,问怎么安装光纤能将所有农场都连通起来,并且要使光纤距离最小,输出安装光纤的总距离。任意两个村庄之间的距离小于 100,000.
分析:连通+距离最小 = 最小生成树
Prim算法适用于稠密图, Kruskal适用于稀疏图
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 110, INF = 0x3f3f3f3f;
int n, m, g[N][N], f[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; }
} t[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 = 1; i <= n; i++) {
int u = -1;
for (int j = 1; j <= n; j++)
if (!st[j] && (u == -1 || dis[j] < dis[u]))
u = j;
if (i > 1 && dis[u] == INF) return -1;
if (i > 1) ans += dis[u];
for (int j = 1; j <= n; j++)
if (dis[j] > g[u][j]) dis[j] = g[u][j];
st[u] = 1;
}
return ans;
}
int find(int u) {
return u == f[u] ? u : f[u] = find(f[u]);
}
int kruskal() {
sort(t + 1, t + 1 + m);
for (int i = 0; i <= n; i++) f[i] = i;
int ans = 0, cnt = 0;
for (int i = 1; i <= m; i++) {
int fu = find(t[i].u), fv = find(t[i].v);
if (fu != fv) f[fu] = fv, ans += t[i].w, cnt++;
if (cnt == n - 1) break;
}
return cnt==n-1?ans:-1;
}
int main() {
while (~scanf("%d", &n)) {
m=0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
scanf("%d", &g[i][j]);
t[++m] = T(i, j, g[i][j]);
}
}
// printf("%d\n", prim());
printf("%d\n", kruskal());
}
return 0;
}

浙公网安备 33010602011771号