P3366 【模板】最小生成树

题目描述

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

输入输出格式

输入格式:

第一行包含两个整数N、M,表示该图共有N个结点和M条无向边。(N<=5000,M<=200000)

接下来M行每行包含三个整数Xi、Yi、Zi,表示有一条长度为Zi的无向边连接结点Xi、Yi

输出格式:

输出包含一个数,即最小生成树的各边的长度之和;如果该图不连通则输出orz

输入输出样例

输入样例#1:  复制
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
输出样例#1:  复制
7

说明

时空限制:1000ms,128M

数据规模:

对于20%的数据:N<=5,M<=20

扫描二维码关注公众号,回复: 1751977 查看本文章

对于40%的数据:N<=50,M<=2500

对于70%的数据:N<=500,M<=10000

对于100%的数据:N<=5000,M<=200000

样例解释:

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

#include<bits/stdc++.h>

using namespace std;

int n , m;
const int MAXN = 400000 + 10;
int g[5010] , First[MAXN], Next[MAXN], book[MAXN];
int ans;

struct f
{
    int u ;
    int v;
    int w;
}a[MAXN];
int find(int x)
{
    while(x != g[x])
        x = g[x] = g[g[x]];
    return x;
}

int com(const f &b, const f &c)
{
    return b.w < c.w;
}

void kruskal()
{
    int num = 0;
    sort(a + 1, a + 2*m + 1, com);
    for(int i = 1 ; i < m * 2; i ++ )
    {
        int q1 = find(a[i].u) , q2 = find(a[i].v);
        if(q1 == q2)
            continue;
        ans += a[i].w;
        g[q2] = q1;
        num ++;
        if(num == n - 1)
            break;
    }
}

int main()
{

    //int n , m
    cin >> n >> m;
    for(int i = 1; i <= n ; i ++)
        g[i] = i;
    for(int i = 1; i <= m ; i ++)
    {
        scanf("%d%d%d", &a[i].u, &a[i].v, &a[i].w);
        Next[i] = First[i]; First[i] = a[i].u;
        a[ i + m ].u = a[i].v; a[ i + m].v = a[i].u ; a[ i + m ].w = a[i].w;
        Next[ i + m ] = First[ i + m ]; First[ i + m ] = a[ i + m ].u;
        book[ a[i].u ] = 1;book[ a[i].v ] = 1;
    }
    for(int i = 1; i <= n ; i ++ )
        if(book[i] == 0 )
        {
            cout << "orz";
            return 0;
        }
    kruskal();
    printf("%d", ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Ant_e_zz/article/details/80791761
今日推荐