例题:联络员
#include <bits/stdc++.h>//采用Kruskal算法
using namespace std;
int n,m,p,fa[10005],ans;
struct node//路径
{
int s,e,w;
} a[10005];
bool cmp(node a, node b)//结构体排序
{
return a.w < b.w;
}
int find(int x)//寻找该点的根节点并在沿途中压缩路径
{
if (fa[x] != x) fa[x] = find(fa[x]);
return fa[x];
}
void unionn(int x, int y)
{
x = find(x);
y = find(y);
fa[y] = x;
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++) fa[i] = i;//初始化
for (int i = 1; i <= m; i++)
{
cin >> p >> a[i].s >> a[i].e >> a[i].w;
int x = find(a[i].s), y = find(a[i].e);
if (p == 1)//如果是必选路线就合并并查集,并将权值加在结果上
{
unionn(x,y);
ans += a[i].w;
}
}
sort(a+1, a+m+1, cmp);
for (int i = 1; i <= m; i++)
{
int x = find(a[i].s), y = find(a[i].e);
if (x != y)//Kruskal算法中判断该边是否会造成回环
{
unionn(x,y);
ans += a[i].w;
}
}
cout << ans << endl;
return 0;
}