- 题目大意
某地发洪水,导致某些城市被淹而消失,现在想把剩下的零散的城市通过修路连接起来,已知现在有部分城市是连通的。可选择修的路有m条,城市总共有n个,给出了m条路的起点终点和修路花费,问最少可花多少钱能保证所有的城市连通。
- 解题思路
可以用kruskal。把边权排序然后并查集添加边即可。
- 代码
#include<algorithm>
#include<cstdio>
using namespace std;
int fa[505];
struct Edge {
int u, v, w;
bool operator<(const Edge &rhs)const {
return w < rhs.w;
}
}e[25005];
void init(int n)
{
for (int i = 1; i <= n; i++)
fa[i] = i;
}
int find(int x)
{
if (x == fa[x])
return x;
else
{
return fa[x] = find(fa[x]);
}
}
bool Union(int x, int y)
{
int fx = find(x), fy = find(y);
if (fx == fy)
return false;
else
{
fa[fx] = fy;
return true;
}
}
void kruskal(int m,int k)
{
int sum = 0;
sort(e, e + m);
for (int i = 0; i < m; i++)
{
int u = e[i].u, v = e[i].v, w = e[i].w;
if (Union(u, v))
{
sum += w;
k--;
}
}
if (!k)
printf("%d\n", sum);
else
{
printf("-1\n");
}
}
int main()
{
int n,m,t,p,q,c,k,tmp;
scanf_s("%d",&t);
while (t--)
{
scanf_s("%d%d%d",&n,&m,&k);
init(n);
for (int i = 0; i < m; i++)
scanf_s("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
tmp = n-1;
for (int j = 0; j < k; j++)
{
scanf_s("%d%d",&p,&q);
while (--p)
{
scanf_s("%d", &c);
if (Union(q,c))
{
tmp--;
}
}
}
kruskal(m, tmp);
}
return 0;
}