/**
* 最小生成树(入门) Kruskal算法:
* 这题输入的数据其实有一半一上是根本不需要存的。因为依题意这是个无向图
* 而且看样例也看得出,对角线及以下(或以上)都是可以省去的。
* 这样在存数据的时候直接存当j > i的时候(也就是上三角的数据),都将数据
* 存到nodes[]中,node表示边,存两点和权值。
* 根据Kruskal算法,首先对边按权值排序,然后遍历选择边就行了.
* 选择的边的依据就是看当前的两个点是否在不同的连通分量中。是的话就选这边(贪心思想)
* 因为已经对权值排序了。
* 最后就是如何判断是否处于不同连通分量。 这个用并查集很容易的。
*/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <algorithm>
#define DEBUG 0
#define INF 0x7fffffff
#define MAXS 101
typedef long long LL;
using namespace std;
int fa[MAXS], n, cnt;
struct Node {
int d, u, v;
bool operator < (const Node &a) const {
return d < a.d;
}
} nodes[100005];
int get_fa(int x) {
return fa[x] == x ? x : fa[x] = get_fa(fa[x]);
}
void Union(int x, int y) {
x = get_fa(x); y = get_fa(y);
fa[x] = y;
}
void init() {
for(int i = 1; i <= n; i ++)
fa[i] = i;
}
void input() {
int cur;
cnt = 0;
for(int i = 1; i <= n; i ++) {
for(int j = 1; j <= n; j ++) {
scanf("%d", &cur);
if(j > i) {
nodes[cnt].u = i;
nodes[cnt].v = j;
nodes[cnt ++].d = cur;
}
}
}
}
void solve() {
sort(nodes, nodes + cnt);
int ans = 0;
for(int i = 0; i < cnt; i ++) {
if(get_fa(nodes[i].u) != get_fa(nodes[i].v)) {
ans += nodes[i].d;
Union(nodes[i].u, nodes[i].v);
}
}
printf("%d\n", ans);
}
int main()
{
while(scanf("%d", &n) != EOF) {
init();
input();
solve();
}
return 0;
}
POJ 1258 Agri-Net 最小生成树(Kruskal算法入门)
最新推荐文章于 2023-08-06 16:59:19 发布