Taoran123 @ 2024-03-26 22:07:41
#include<iostream>
#include<algorithm> //sort()所在头文件
using namespace std;
int n,m;//n为节点数,m为边数
int ans=0;
int father[5001] ;//记录每个点所在树的父结点 (kruskal在不断合并树)
int f[5001][5001];
struct Edge
{
int u,v;
int weight; //边权
}edge[200001];
bool cmp(Edge a,Edge b)//结构体的sort规则
{
return a.weight<b.weight;//按edge.weight值 从小到大排序
}
int findf(int x) //并查集 找祖宗并返回(1.压缩路径 2.途经点的父亲都改为了祖宗点)
{
if(father[x]==x)
{
return x;
}
else {
father[x]=findf(father[x]);//找祖宗
}
}
void Kruskal()//kruskal时间复杂度eloge
{
//步骤1 排序边权,初始化
int tot=0;
sort(edge+1,edge+m+1,cmp) ;//排序 (从结构体数组edge的序号1到序号m)
for(int i=1;i<=n;i++) father[i]=i;//初始化父节点也就是并查集
//步骤2 从小到大添加边,利用并查集合并不同的树(也就避免了产生回路)
for(int i=1;i<=m;i++) //从小到大遍历边
{
int uf,vf;
uf=findf(edge[i].u) ;vf=findf(edge[i].v) ;
if(uf!=vf)//如果不在同一个树,合并两棵树 (也就是加上这个边)
{
tot++;
ans+=edge[i].weight;
father[edge[i].u] =edge[i].v;//让u的父亲是v,这样下次findf时候会①自动把u的父亲改为v的父亲,②其他点经过u时候也会把父亲改为v的父亲
}
if(tot==n-1)
{
cout<<ans;
break;
}
}
if(tot!=n-1)
{
cout<<"orz";
}
}
int main(){
//读入
cin>>n>>m;//读入节点数、边数
for(int i=1;i<=m;i++)//将边的信息读入
{
int u,v,w;//节点u到节点m的边 权值为w
if(u!=v)//去掉自环
{
cin>>u>>v>>w;
}
if(f[u][v]==0)//去掉重边
{
edge[i].u=u;
edge[i].v=v;
edge[i].weight=w;
f[u][v]=w;
f[v][u]=w;
}
else if(f[u][v]>w){
edge[i].u=u;
edge[i].v=v;
edge[i].weight=w;
f[u][v]=w;
f[v][u]=w;
}
/*cin>>u>>v>>w;
edge[i]={u,v,w};//把边信息存入结构体edge[i]
*/
}
Kruskal();//使用kruskal算法进行稀疏图的最小生成树生成。
return 0;
}
}
int main(){ //读入 cin>>n>>m;//读入节点数、边数 for(int i=1;i<=m;i++)//将边的信息读入 { int u,v,w;//节点u到节点m的边 权值为w if(u!=v)//去掉自环 { cin>>u>>v>>w; } if(f[u][v]==0)//去掉重边 { edge[i].u=u; edge[i].v=v; edge[i].weight=w; f[u][v]=w; f[v][u]=w; } else if(f[u][v]>w){ edge[i].u=u; edge[i].v=v; edge[i].weight=w; f[u][v]=w; f[v][u]=w; }
/*cin>>u>>v>>w;
edge[i]={u,v,w};//把边信息存入结构体edge[i]
*/
}
Kruskal();//使用kruskal算法进行稀疏图的最小生成树生成。
return 0;
}
by __ryp__ @ 2024-03-26 22:32:33
@Taoran123 并查集 else 分支没 return
by __ryp__ @ 2024-03-26 22:33:29
@Taoran123 另外这题不需要判重边
by Taoran123 @ 2024-03-26 22:55:08
@intirain 改了一下变成后3个ac,前面的全都是输出o