#include

51nod_1212_无向图最小生成树(模板题)

1212 无向图最小生成树

基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题
 
N个点M条边的无向连通图,每条边有一个权值,求该图的最小生成树。
 
Input
第1行:2个数N,M中间用空格分隔,N为点的数量,M为边的数量。(2 <= N <= 1000, 1 <= M <= 50000)
第2 - M + 1行:每行3个数S E W,分别表示M条边的2个顶点及权值。(1 <= S, E <= N,1 <= W <= 10000)
Output
输出最小生成树的所有边的权值之和。
Input示例
9 14
1 2 4
2 3 8
3 4 7
4 5 9
5 6 10
6 7 2
7 8 1
8 9 7
2 8 11
3 9 2
7 9 6
3 6 4
4 6 14
1 8 8
Output示例
37

prim 每次向树中加一个点
// prim
#include <iostream>
#include <algorithm>

using namespace std; 


#define maxn 1005 
#define INF 99999999

bool visit[maxn]; 
int min_dis[maxn]; 
int map_dis[maxn][maxn]; 

int n, m;
int s, e, w;

int prim() {
    
    for (int i = 0; i < n; i++) {
        visit[i] = false; 
        min_dis[i] = INF; 
        
    }
    
    min_dis[0] = 0; 
    // visit[0] = true; 
    int sum = 0;

    
    while (true) {
        int pos = -1;

        for (int i = 0; i < n; i++) {
            if (!visit[i] && (pos == -1 || min_dis[i] < min_dis[pos])) {
                pos = i;
            }
        }

        // cout << 1 << endl;

        if (pos == -1) {
            break; 
        }
        else {

            sum += min_dis[pos];
            //cout << "sum = " << sum << endl;
            //cout << "pos = " << pos << endl; 
        }

        visit[pos] = true;

        for (int i = 0; i < n; i++) {
            if (!visit[i] && map_dis[pos][i] < min_dis[i]) {
                min_dis[i] = map_dis[pos][i];
            }
        }
    }
    return sum; 
}

int main() {

    while (cin >> n >> m) {

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                map_dis[i][j] = INF; 
            }
        }

        for (int i = 0; i < m; i++) {
            cin >> s >> e >> w;
            s -= 1; 
            e -= 1;

            map_dis[s][e] = w; 
            map_dis[e][s] = w; 
        }

        int result = prim(); 

        cout << result << endl; 
    }
    return 0; 
}

Kruskal 每次向树中加一条边

// Kruskal 
#include <iostream>
#include <algorithm>

using namespace std; 

#define maxn 60000
int father[maxn];
int son[maxn]; 


struct line {
    int a,
        b,
        value; 
};

// 边按权值大小排序
bool cmp(line & a, line & b) {
    return a.value < b.value; 
}

int check_tree_root(int x) {
    // 递归找到 树根 并返回
    return x == father[x] ? x : check_tree_root(father[x]); 
}

// 检查 x 和 y 所在的两个树是否可以合并
bool join(int x, int y) {

    int root1 = check_tree_root(x); 
    int root2 = check_tree_root(y); 

    // x 和 y 属于同一棵树
    if (root1 == root2) {
        return false; 
    }
    else {
        // 树根为 root1 的树规模较大
        if (son[root1] >= son[root2]) {
            father[root2] = root1; 
            son[root1] += son[root2]; 
        }
        else {
            father[root1] = root2; 
            son[root2] += son[root1]; 
        }
    }

    return true; 
}

int main() {
    
    int v, e; 

    line node[maxn]; 

    cin >> v >> e; 

    for (int i = 0; i < e; i++) {
        cin >> node[i].a >> node[i].b >> node[i].value; 
    }

    for (int i = 0; i <= v; i++) {
        // 初始情况 每个单独的节点都是一颗树
        // 树根是自己本身 , 树的节点数 为 1 
        father[i] = i; 
        son[i] = 1; 
    }

    sort(node, node + e, cmp); 
    
    int sum_e = 0; 
    int sum = 0; 
    bool flag = false; 

    for (int i = 0; i < e; i++) {
        // 如果可以加边
        if (join(node[i].a, node[i].b)) {
            sum_e++; 
            sum += node[i].value; 
        }

        if (sum_e == v - 1) {
            flag = true; 
            break; 
        }
    }

    if (flag == true) {
        cout << sum << endl;
    }
    
    return 0; 
}

 

posted @ 2018-08-05 14:51  0一叶0知秋0  阅读(208)  评论(0编辑  收藏  举报