Kruskal算法
基本思想: 并查集+贪心
操作
首先从小到大排序【贪心】
看最小的边,如果这边的两个结点不是同一个根,【用并查集操作】,则可以合并为一棵新树
#include<bits/stdc++.h>
using namespace std;
struct RoadType{
int GoTop,ToTop,Weight;
bool operator < (const RoadType &x) const
{
return Weight<x.Weight;
}
}Road[10005];
int Father[1005];
void Init(int Many) //并查集初始化
{
for (int i=1; i<=Many; i++) Father[i]=i;
}
int Find(int Top) //并查集中寻找父节点
{
Father[Top]=Father[Top]==Top?Top:Find(Father[Top]);
return Father[Top];
}
void Union(int A, int B) //并查集中合并操作
{
Father[Find(A)]=Find(B);
}
int main()
{
int Many,Un,RMany=0,Choose=0,C_Top=0,Sum=0;
cin >> Many;
for (int i=1; i<=Many; i++)
{
for (int j=1; j<=i; j++) cin >> Un;
for (int j=i+1; j<=Many; j++)
{
cin >> Road[++RMany].Weight;
Road[RMany].GoTop=i;
Road[RMany].ToTop=j;
}
}
sort(Road+1,Road+1+RMany); //贪心最基本操作: 排序
Init(Many);
while (Choose < Many-1 && C_Top <= RMany) //一个n节点的图,最小生成树,只需要选择n-1条边,自己可以画图想一想
{
C_Top++;
if (Find(Road[C_Top].GoTop) != Find(Road[C_Top].ToTop)) //如果不是同一根【即不是同一棵树】,合并
{
Union(Road[C_Top].GoTop,Road[C_Top].ToTop);
Sum+=Road[C_Top].Weight;
Choose++;
}
}
cout << Sum;
}