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;}

原创粉丝点击