SDUT 离散数学 4178 最小生成树

最小生成树

Time Limit: 1000 ms Memory Limit: 65536 KiB

Submit Statistic

Problem Description

在一个无向图中,求最小生成树。

Input

多组测试数据,对于每组测试数据,第1行输入正整数n(1 <= n <= 1000)、m,表示n个顶点(编号从1开始)和m条边。之后m行每行输入u(1 <= u <= n)、v(1 <= v <= n)、w(1 <= w <= 100),表示在顶点u和顶点v之间存在无向边,且权值为w。

Output

对于每组测试数据,若存在最小生成树则输出最小生成树的权值和,若不存在最小生成树则输出-1。

Sample Input

3 7
1 2 19
2 3 11
3 1 7
1 3 5
2 3 89
3 1 91
1 2 32

Sample Output

16

Hint

Source

xry-fhf

 

#include 
using namespace std;
struct node {
    int parent;
    int u, v, w;
} a[102400];

bool cmp(node a, node b) { return a.w < b.w; }

/*下面两个函数是并查集*/
int find_root(int x) {
    if (x == a[x].parent) {
        return x;
    }
    return find_root(a[x].parent);
}

void union_set(int u, int v) {
    int xr = find_root(u);
    int yr = find_root(v);
    a[xr].parent = a[yr].parent;
}

int main() {
    int n, m;
    while (cin >> n >> m) {
        for (int i = 1; i <= m; i++) {
            cin >> a[i].u >> a[i].v >> a[i].w;
        }

        sort(a + 1, a + m + 1, cmp);
        for (int i = 1; i <= n; i++) {  // 每个点的祖宗都是自己
            a[i].parent = i;
        }
        int ans = 0;  // 记录最小的权值和
        int cnt = 0;  // 记录边的个数
        for (int i = 1; i <= m; i++) {
            if (find_root(a[i].u) != find_root(a[i].v)) {
                cnt++;
                ans += a[i].w;
                union_set(a[i].u, a[i].v);  // 将不形成环的两边连起来
            }
        }
        // n个点  n-1条边  否则不能构成最小生成树
        if (cnt == n - 1)
            cout << ans << endl;
        else
            cout << "-1" << endl;
    }
}

 

你可能感兴趣的:(离散数学)