图论-最小生成森林
问题
分析
通过连接一些边,将这些节点连成k个最小生成树,构成的最小生成森林。
我们有一下推断:
含有一颗最小生成树,需要连接n-1条边,含有两颗最小生成树,需要连接n-2条边,含有k颗最小生成树,需要连接n-k条边。
因此,我们只需要连接n-k个边即可,使用Kruskal算法即可。如果没连到n-k条边优先队列就为空了,那么就是无解。
代码
#include <bits/stdc++.h>
using namespace std;
int pre[1005];
int find(int u)
{
return pre[u] == u ? u : pre[u] = find(pre[u]);
}
bool unite(int u, int v)
{
int ur = find(u);
int vr = find(v);
if (ur != vr)
{
pre[ur] = vr;
return true;
}
return false;
}
struct edge
{
int u;
int v;
int w;
bool operator<(const edge &x) const
{
return x.w < w;
}
};
int main()
{
int n, m, k;
cin >> n >> m >> k;
for (int i = 1; i <= n; i++)
{
pre[i] = i;
}
priority_queue<edge> pq;
while (m--)
{
int u, v, w;
cin >> u >> v >> w;
pq.push({u, v, w});
}
int cnt = 0;
int tw = 0;
while (cnt != n - k && !pq.empty())
{
edge e = pq.top();
pq.pop();
if (unite(e.u, e.v))
{
cnt++;
tw += e.w;
}
}
if (cnt == n - k)
{
cout << tw;
}
else
{
cout << "No Answer";
}
return 0;
}