填坑行动5-最小生成树kruskal学习笔记

    技术2022-07-15  46

    文章目录

    板子题题目解析算法解析代码

    板子题

    题目描述 如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 orz。 输入格式 第一行包含两个整数 N , M N,M N,M表示该图共有 N N N个结点和 M M M条无向边。 接下来 M M M行每行包含三个整数 X i , Y i , Z i X_i,Y_i,Z_i Xi,Yi,Zi ,表示有一条长度为 Z i Z_i Zi的无向边连接结点 X i , Y i X_i,Y_i Xi,YiX。 输出格式 如果该图连通,则输出一个整数表示最小生成树的各边的长度之和。如果该图不连通则输出orz。

    题目解析

    首先,我们需要知道最小生成树是什么。 我们知道数是一个没有环的连通图,要在一张图里面找出边权和最小的一棵树就是最小生成树。

    算法解析

    这里我们以kruskal为例来讲解算法。 kruskal首先将每条边按照边权从小到大进行排序,这里通常使用快速排序,就是C++的sort。 然后从小到大来逐个判断这条边是否在同一个连通图内(假设这个图只有我们我们要加上的边),如果不是,就加上这条边。 当然,我们还要使用并查集来维护多个点是否在同一个连通图以内。

    代码

    #include<cstdio> #include<algorithm> #define maxn 200039 using namespace std; struct edge{ int f,t,w; bool operator < (const edge x) const { return this->w < x.w; } }a[maxn]; int f[5039]; int getfa(int x){ if(x==f[x]) return x; f[x]=getfa(f[x]); return f[x]; } int n,m,i,j,k; int main(){ scanf("%d%d",&n,&m); for(i=0;i<=n;i++) f[i]=i; for(i=1;i<=m;i++) scanf("%d%d%d",&a[i].f,&a[i].t,&a[i].w); sort(a+1,a+m+1); int k=0; int ans=0; for(i=1;i<=m;i++){ if(k==n-1){ printf("%d",ans); return 0; } if(getfa(a[i].f)!=getfa(a[i].t)){ f[getfa(a[i].f)]=a[i].t; k++; ans+=a[i].w; } } printf("orz"); return 0; }

    发现自己变sb了连并查集都快不会打了

    Processed: 0.012, SQL: 9