• HDU1233还是畅通工程(最小生成树 Kruskal算法)


    http://acm.hdu.edu.cn/showproblem.php?pid=1233

    //结构体做法

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    int p[101],sum,num;    //p为并查集
    struct edge//图的结构体
    {
        int sv,ev,w;//起始边,终边,权值。
    };
    
    struct edge e[10000];//必须开到大于(n*n-1)/2,否则必然RE。。。
    
    int comp(const void *a,const void *b){
        return (*(struct edge*)a).w > (*(struct edge*)b).w ?1:-1;
    }
    
    int find(int x){//并查集find函数
        return p[x] == x ? x : (p[x] = find(p[x]));//压缩路径
    }
    
    void merge(int x,int y,int w){//并查集merge函数
        x = find(x); y = find(y);
        if(x != y){
            p[x] = y; sum += w; num++;
        }
    }
    
    int main(){
        int n,m,i;
        while(scanf("%d",&n)==1 && n != 0)
        {
            sum = 0; num = 1;
            m = n*(n-1)/2;
            for(i = 1;i <= n;i ++) p[i] = i;//初始化并查集
            for(i = 0;i < m;i ++){
                scanf("%d %d %d",&e[i].sv,&e[i].ev,&e[i].w);
            }
            qsort(e,m,sizeof(e[0]),comp);//调用结构体快排
            for(i = 0; i < m; i++){
                merge(e[i].sv,e[i].ev,e[i].w;
                if(num == n) break;
            }
            printf("%d\n",sum);
        }
        return 0;
    }



    //直接数组

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define MAXN 6000
    
    int u[MAXN], v[MAXN], w[MAXN], r[MAXN], p[MAXN];
    
    int cmp(const void *a, const void *b){
        int x = *(int *)a, y = *(int *)b;
        return w[x] - w[y];
    }
    
    int find(int x){return p[x] == x ? x : (p[x] = find(p[x]));}
    
    int Kruskal(int n, int m){
        int ans = 0, i;
        for(i=0; i<n; i++) p[i] = i;//初始化并查集
        for(i=0; i<m; i++) r[i] = i;//初始化边号
        qsort(r, m, sizeof(r[0]), cmp);
        for(i=0; i<m; i++){
            int e = r[i]; int x = find(u[e]); int y = find(v[e]);
            if(x != y) {ans += w[e]; p[x] = y;}
        }
        return ans;
    }
    
    int main(){
        int n, m, i;
        while(scanf("%d", &n) == 1 && n != 0){
            m = n*(n-1)/2;
            for(i=0; i<m; i++){
                scanf("%d %d %d", &u[i], &v[i], &w[i]);
                u[i]--; v[i]--;//从零开始编号
            }
            printf("%d\n", Kruskal(n, m));
        }
        return 0;
    }
    
    //如果是从1开始编号 只需要注释掉
    //u[i]--; v[i]--;
    //并且把for(i=0; i<n; i++) p[i] = i;//初始化并查集
    //改成for(i=1; i<=n; i++) p[i] = i;//初始化并查集


  • 相关阅读:
    设计模式-创建型-原型模式
    设计模式-创建型-抽象工厂模式
    设计模式-创建型-工厂模式
    设计模式-创建型-单例模式
    css3技巧属性之text-overflow
    bootstrap如何自定义5等分
    LeetCode-64-最小路径和
    LeetCode-62-不同路径
    LeetCode-5-最长回文子串
    LeetCode-98-验证二叉搜索树
  • 原文地址:https://www.cnblogs.com/tanhehe/p/2883507.html
Copyright © 2020-2023  润新知