第一行国际惯例——咕咕咕。
本代码以sdnu1218为例
1.类似贪心的策略,先对边按权值进行排序,不停的选择最优边进行构建树
2.在构建过程中需要判断是否有环(并查集判断(如果不会并查集(我改天再补一下并查集博客
3.忽略我特别丑的代码风格
4.可以增加优化(在kruskal函数的循环里加一个提前跳出的操作,当边的个数>n-1时跳出即可(n为点的个数(最小生成树最多n-1条边(此处略过
5.时间复杂度与边的个数有关(适合稀疏图
6.先写kruskal是因为我prim不会写(这个晚上看了2/3时间的prim都不会写(我果然菜的很
这个题是最小生成树而不是最短路是因为它起点不固定的情况下遍历所有点且每条路只能走一次
#include <iostream>
#include <cstdio>
#include <algorithm>
#define inf 999999999999
#define maxn 200005
using namespace std;
int fa[maxn];
int n,m;
struct tree
{
int u;
int v;
int cost;
} t[maxn];//用于存每条边
void init()
{
for(int i=0; i<maxn; ++i)
{
t[i].cost=inf;
fa[i]=i;
}
}//初始化所有的权值为max,所有的父节点为其本身
bool com(tree x,tree y)
{
if(x.cost<y.cost)
return true;
else
return false;
}//按权值从小到大排序
int tofind(int x)
{
while(fa[x]!=x)
{
x=fa[x];
}
return x;
}//找到每个点的父节点
void tojoin(int x,int y)
{
x=tofind(x);
y=tofind(y);
if(x!=y)
fa[x]=y;
}//合并两棵树
int kruskal()
{
int ans=0;
for(int i=0; i<m; ++i)
{
int u=t[i].u;
int v=t[i].v;
if(tofind(u)==tofind(v))
continue;//当两个点的父节点为同一节点(即早已联通,下一个循环
ans+=t[i].cost;
tojoin(u,v);//合并两个为同一个棵树
}
return ans;
}
int main()
{
init();
scanf("%d%d",&n,&m);
for(int i=0; i<m; ++i)
{
int u,v,cost;
scanf("%d%d%d",&t[i].u,&t[i].v,&t[i].cost);
}//将每个边储存
sort(t,t+m,com);//排序
printf("%d\n",kruskal());
return 0;
}
//后期应该会更新几个练习题