最小生成树

Kruskal算法

①设含有0条边的生成子图为A

②在边集合中,找取权值最低的边,且它不与子图A中的任意条边构成闭环,则将其加入到子图A中

③重复②,直到边数满足N-1

 

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
struct edge {
    int a, b;
    int w;
};

int n, T, m, sum;
edge se[20000];//储存边 

int set[2000];//辅助集合 

bool cmp(edge e1, edge e2) {
    return e1.w > e2.w;
}

int find(int x) {
    return x == set[x] ? x : set[x] = find(set[x]);
}

void MSt() {
    for (int i = 1; i <= n; i++)
        set[i] = i;

    int num = 0;
    int k = 0;
    while (k < n - 1) {
        int a = find(set[se[num].a]);

        int b = find(set[se[num].b]);

        if (a != b) {
            sum += se[num].w; 
            set[b] = a;
            k++;
        }
        num++;
    }
}


int main() {
    scanf("%d", &T);
    while (T--) {
        sum = 0;
        scanf("%d %d", &n, &m);
        //读入m条边 
        for (int i = 0; i < m; i++) {
            int a = 1, b = 1, w = 1;
            scanf("%d %d %d", &a, &b, &w);
            se[i].a = a;
            se[i].b = b;
            se[i].w = w;
        }
        //根据权值把边排序 
        sort(se, se + m, cmp);

        MST();
        
        cout << sum << endl;
    }
    return 0;
}

 

 

 

下面的代码,如果是同一个集合中的顶点,那么set[ i ] = set[ j ],这样的话就要遍历,比较麻烦,需要修改多处。

    while(k < N - 1){
        if(set[se[num].a] != set[se[num].b]){
            cout<<se[num].a+1<<" "<<se[num].b+1<<endl;
            int t = set[se[num].b];
            //将所有与se[num].b一个集合的元素 全放到se[num].a所在集合中 
            for(int i=0;i<N;i++){
                if(set[i] == t)
                    set[i] = set[se[num].a];
            }
            k++;
        }
        num++;
    } 
}

Prime算法

 

posted @ 2019-01-21 23:15  阳离子  阅读(180)  评论(0编辑  收藏  举报