POJ 1258 Agri-Net 最小生成树(Kruskal算法入门)
来源:互联网 发布:万年历c语言程序 编辑:程序博客网 时间:2024/06/06 00:59
/*** 最小生成树(入门) 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 101typedef 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;}