上模板
const int MAX = 999999;
struct edg {
//边的起点,终点,权值
int start, end, value;
edg(){}
edg(int s, int e, int v) {
start = s;
end = e;
value = v;
}
bool operator<(const edg& a)const
{
return value < a.value;
}
}ed[MAX];
int cnt = 0;
//加边函数
void add(int s,int e,int v)
{
cnt++;
ed[cnt].start = s;
ed[cnt].end = e;
ed[cnt].value = v;
}
int fat[MAX];
int father(int x) {
if (x != fat[x])
return father(fat[x]);
else
return x;
}
void kruskal() {
//初始化并查集
for (int i = 1; i <= cnt; i++)
{
fat[i] = i;
}
sort(ed, ed + cnt);//给边按权值大小排序
int ans = 0,num=0;
for (int i = 1; i <= cnt; i++)
{
//最小生成树有n-1条边
if (num==n-1)
{
break;
}
//若该边起点终点不属于同一树支
if (father(ed[i].start)!=father(ed[i].end))
{
ans += ed[i].value;//累加权值
fat[ed[i].end] = ed[i].start;//联通两个支
num++;//加了一条边
}
}
cout << ans << endl;
}
kruskal算法核心其实挺简单,主要步骤如下:
1.对所有边按照权值从小到大排序;
2.从小到大取出边,利用并查集判断该边是否可以选取(就是判断是否成环);
3.若取出的边到达了顶点数-1条,则这些边共同构成的树就是最小生成树。
算法核心部分简单,主要是注意细节如并查集,单双向边等,根据不同题目变换模板即可。