Connect the Cities
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 15569 Accepted Submission(s): 4108
Problem 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.
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条路的信息,和已经连接上的K个城市信息。
接下来m行每行是城市A到B建路需要的花费。再接下来k行每行第一个数为t,之后t个数表示已经连接在一起的城市。
在已经连接的基础上进行城市间的连通,求解全部联通的最少费用。不能连通输出-1
典型的kruskal算法,并查集和贪心算法求解最小生成树,最后判断城市生成的树是否唯一。
这题非常奇怪,用JAVA死活TLE,然后又用c++写,然后还是超时,然后又把启发式搜索什么的加进去也没用,最后改成g++就过了..过了。。
#include <stdio.h> #include <algorithm> #include <string.h> using namespace std; int father[505]; int dep[505]; struct Seg { int x,y,len; } seg[25010]; int cmp(Seg a,Seg b) { return a.len <b.len; } int _find(int x) { if(x==father[x])return x; return _find(father[x]); } int main() { int tcase ; scanf("%d",&tcase); while(tcase--) { int n,m,t; scanf("%d%d%d",&n,&m,&t); for(int i=1; i<=n; i++) { father[i]=i; dep[i]=0; } for(int i=0; i<m; i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); seg[i].x=x; seg[i].y=y; seg[i].len=z; } for(int i=0; i<t; i++) { int num,x; scanf("%d%d",&num,&x); num--; while(num--) { int y; scanf("%d",&y); x = _find(x); y = _find(y); if(x!=y) { if(dep[x]==dep[y]) { father[x] = y; dep[y]++; } else if(dep[x]<dep[y]) { father[x] = y; } else { father[y]=x; } } } } sort(seg,seg+m,cmp); int sum=0; for(int i=0; i<m; i++) { int x = _find(seg[i].x); int y = _find(seg[i].y); if(x!=y) { if(dep[x]==dep[y]) { father[x] = y; dep[y]++; } else if(dep[x]<dep[y]) { father[x] = y; } else { father[y]=x; } sum+=seg[i].len; } } int ans=0; for(int i=1; i<=n; i++) { if(father[i]==i) ans++; } if(ans==1) printf("%d ",sum); else printf("-1 "); } return 0; }