zoukankan      html  css  js  c++  java
  • P3366 【模板】最小生成树 (贪心+并查集,kruskal)

    题目描述

    如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 orz

    输入格式

    第一行包含两个整数 N,MN,M,表示该图共有 NN 个结点和 MM 条无向边。
    接下来 MM 行每行包含三个整数 X_i,Y_i,Z_iXi​,Yi​,Zi​,表示有一条长度为 Z_iZi​ 的无向边连接结点 X_i,Y_iXi​,Yi​。

    输出格式

    如果该图连通,则输出一个整数表示最小生成树的各边的长度之和。如果该图不连通则输出 orz

    输入输出样例

    输入 #1
    4 5
    1 2 2
    1 3 2
    1 4 3
    2 3 4
    3 4 3
    输出 #1
    7

    说明/提示

    数据规模:

    对于 20\%20% 的数据,Nle 5N≤5,Mle 20M≤20。
    对于 40\%40% 的数据,Nle 50N≤50,Mle 2500M≤2500。
    对于 70\%70% 的数据,Nle 500N≤500,Mle 10^4M≤104。
    对于 100\%100% 的数据:1le Nle 50001≤N≤5000,1le Mle 2 imes 10^51≤M≤2×105。

    样例解释:

    所以最小生成树的总边权为 2+2+3=72+2+3=7.

    题解:

    该题可以利用贪心的思想,将所有边按照权值从小到大进行排列,从最小的开始取,一定就是最短路,同时利用并查集来判断两个点是否已经连通。具体见代码。

    #define _CRT_SECURE_NO_DepRECATE
    #define _CRT_SECURE_NO_WARNINGS
    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <iomanip>
    #include <string>
    #include <algorithm>
    #include <bitset>
    #include <cstdlib>
    #include <cctype>
    #include <iterator>
    #include <vector>
    #include <cstring>
    #include <cassert>
    #include <map>
    #include <queue>
    #include <set>
    #include <stack>
    #include <stdio.h>
    #define ll long long
    #define INF 0x3f3f3f3f
    #define LINF 0x3f3f3f3f3f3f3f3f
    #define ld long double
    #define rep(i, a, b) for(int i = a; i < (b); ++i)
    const ld pi = acos(-1.0L), eps = 1e-8;
    ll qx[4] = { 0,0,1,-1 }, qy[4] = { 1,-1,0,0 }, qxx[2] = { 1,-1 }, qyy[2] = { 1,-1 };
    using namespace std;
    int n, m, a, b, c, d, e, ans = 0, cnt = 0;
    struct node
    {
        int parent, shu;
    }shu[10010];
    struct nodee
    {
        int x, y, z;//x,y为点 z为权值
    }tu[200010];
    bool cmp(nodee x, nodee y)//排序权值
    {
        return x.z < y.z;
    }
    int find(int x)
    {
        while (shu[x].parent != x)
        {
            x = shu[x].parent = shu[shu[x].parent].parent;
        }
        return x;
    }
    inline void kruskal()
    {
        sort(tu, tu + m, cmp);
        rep(i, 0, m)
        {
            d = find(tu[i].x);
            e = find(tu[i].y);
            if (d == e)//当两点已连通则换下一条边
            {
                continue;
            }
            ans += tu[i].z;
            shu[d].parent = e;//合并
            if (++cnt == n - 1)//已经全部合并的时候就结束循环
            {
                break;
            }
        }
    }
    int main() 
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cout.tie(0);
        cin >> n >> m;
        for (int i = 1; i <= n; i++)
        {
            shu[i].parent = i;
        }
        rep(i, 0, m)
        {
            cin >> tu[i].x >> tu[i].y >> tu[i].z;
        }
        kruskal();
        if (ans == 0)
        {
            cout << "orz" << endl;
            return 0;
        }
        cout << ans << endl;
        return 0;
    }
  • 相关阅读:
    easy ui 表单ajax和from两种提交数据方法
    easy ui 下拉级联效果 ,下拉框绑定数据select控件
    easy ui 下拉框绑定数据select控件
    easy ui 异步上传文件,跨域
    easy ui 菜单和按钮(Menu and Button)
    HTTP 错误 404.3
    EXTJS4.2 后台管理菜单栏
    HTML 背景图片自适应
    easy ui 表单元素input控件后面加说明(红色)
    EXTJS 4.2 添加滚动条
  • 原文地址:https://www.cnblogs.com/Load-Star/p/12853908.html
Copyright © 2011-2022 走看看