您的位置:首页 > 其它

文章标题 HDU 3371 : Connect the Cities(最小生成树--Kruskal+并查集)

2016-10-30 21:08 561 查看

Connect the Cities

Description

In 2100, since the sea level rise, most of the cities disappear. Though some survived cities are still connected with others, but most of them become disconnected. The government wants to build some roads to connect all of these cities again, but they don’t want to take too much money.

Input

The first line contains the number of test cases.

Each test case starts with three integers: n, m and k. n (3 <= n <=500) stands for the number of survived cities, m (0 <= m <= 25000) stands for the number of roads you can choose to connect the cities and k (0 <= k <= 100) stands for the number of still connected cities.

To make it easy, the cities are signed from 1 to n.

Then follow m lines, each contains three integers p, q and c (0 <= c <= 1000), means it takes c to connect p and q.

Then follow k lines, each line starts with an integer t (2 <= t <= n) stands for the number of this connected cities. Then t integers follow stands for the id of these cities.

Output

For each case, output the least money you need to take, if it’s impossible, just output -1.

Sample Input

1

6 4 3

1 4 2

2 6 1

2 3 5

3 4 33

2 1 2

2 1 3

3 4 5 6

Sample Output

1

题意:由于海平面上升,一些城市被淹没了,但剩下来的城市有些还有保持联系,但大部分失去了联系。现要将所有的城市都能联系起来,但想花费最少的金钱。输入n,m,k,表示现有n个城市,然后m表示有m条路径可以建立,p和q连接需要花费c的金钱。然后接下来的k行,每一行中第一个数表示接下来的t个城市还保持着联系。最后要求出总共最少需要多少金钱将所有城市联系起来,如果不能联系起来输出-1。

分析:很明显这是最小生成树的题,用Kruskal算法,首先将已经联系的城市联系起来,算出已经有多少条边已经建立起来,然后将m条边排一下序,从花费最小的往里加,当刚好有n-1条边建立的时候说明城市已经联系起来了。最后判断一下是不是只有一颗树。

代码:

#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
#include<vector>
#include<math.h>
#include<map>
#include<queue>
#include<algorithm>
using namespace std;
const int inf = 0x3f3f3f3f;
int n,m,k;
struct node {
int x,y,cost;
};
node a[25005];
bool cmp(node a,node b){//按花费小的排序
return a.cost < b.cost;
}
int con[505];
int fa[25005];
void init (){//初始化
for (int i=1;i<=n;i++){
fa[i]=i;
}
}
int find(int x){
return fa[x]==x?x:fa[x]=find (fa[x]);
}
int main ()
{
int t;
scanf ("%d",&t);
while (t--){
int cnt=0;
scanf ("%d%d%d",&n,&m,&k);
init();
for (int i=0;i<m;i++){
scanf ("%d%d%d",&a[i].x,&a[i].y,&a[i].cost);
}
int sum;
for (int i=0;i<k;i++){
scanf ("%d",&sum);
for (int j=0;j<sum;j++){//将原先保持联系的城市建立起来
scanf ("%d",&con[j]);
if (j==0)continue;
int fu=find(con[j-1]);
int fv=find(con[j]);
if (fu!=fv){
cnt++;//边数加一
fa[fu]=fv;
}
}
}
sort(a,a+m,cmp);//排序,然后往里加
long long ans=0;
for(int i=0;i<m;i++){
int f1=find(a[i].x);
int f2=find(a[i].y);
if (f1!=f2){
ans+=a[i].cost;
fa[f1]=f2;
cnt++;
}
if (cnt==n-1)break;
}
int flag=1;
int count=0;
if (cnt<n-1)flag=0;//如果边数小于n-1,说明没发将n个城市建立联系
if (flag){
printf ("%lld\n",ans);
}
else {
printf ("-1\n");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: