洛谷P3366 【模板】最小生成树

来源:互联网 发布:ubuntu 中文输入 编辑:程序博客网 时间:2024/06/01 19:13

题目描述

如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出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
对于40%的数据:N<=50,M<=2500
对于70%的数据:N<=500,M<=10000
对于100%的数据:N<=5000,M<=200000

-----------------------------------------华丽的分界线-----------------------------------------

模板题。

克鲁斯卡尔算法就行。

不过多解释,简单说明一下。

如果你忘记了并查集,赶快恶补。

输入图之后(我按结构体输入的),按边权排序。

从最小的边遍历。

如果两边的点的祖先点不同,这条边算上。

重复,直到已经有n-1条边,完事。

然后,上代码。

当然需要初始化,把自己的祖先设为自己。

#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <ctime>#include <iostream>#include <queue>#include <vector>#include <algorithm>using namespace std;int n;int m;struct NODE{    int u;    int v;    int w;};//存图结构体NODE node[200005];//习惯单独定义,不单列也行int fa[5005];//记录祖先int ans;//结果bool cmp(NODE,NODE);//比较int find(int);//找祖先bool check();int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=m;i++)        scanf("%d%d%d",&node[i].u,&node[i].v,&node[i].w);    sort(node+1,node+m+1,cmp);    //结构体排序    for(int i=1;i<=n;i++)        fa[i]=i;    //初始化    int tot;    tot=0;    for(int i=1;i<=m;i++)//遍历    {        if(find(node[i].u)!=find(node[i].v))        {            fa[find(node[i].v)]=find(node[i].u);            tot+=node[i].w;        }    }    printf("%d",tot);    return 0;}bool cmp(NODE a,NODE b){    if(a.w<b.w)        return true;    else        return false;}int find(int x){    if(fa[x]==x)        return x;    else        return fa[x]=find(fa[x]);}bool check(){    int len;    len=find(1);    for(int i=2;i<=n;i++)    {        if(find(fa[i])==len)            continue;        else            return false;    }    return true;}


原创粉丝点击