1
题目大意:首先是T组数据,之后每组第一行是N M K,表示N个城市,M条路的信息,和
已经连接上的K个城市信息。接下来M行每行是城市A到B建路需要的花费。再接下来K行每
行第一个数为t,之后t个数表示已经连接在一起的城市。简单说,就是给你N个城市和M条
路的花费,再给你已经联通的城市,求连接所有城市的最小生成树总权值是多少。
思路:用kruskal算法来做,先把联通的城市并入集合,再依次并入边权值最小的边,直到
并到N-1条边,就生成了最小生成树。如果并完了没有达到N-1条边,就是不能联通,输出
"-1"。这道题昨天写的,提交了23次,不是TLE就是栈溢出,最后发现:把cin改为scanf,
再把sort改为qsort就不超时了。。。前边的我理解,后边的就比较无语了。。。
原来sort用C++提交会超时,G++就不会超时。。。但是不知道原理,求大神解释。。。
AC代码:
#include<stdio.h> #include<string.h> #include<stdlib.h> struct Node { int from; int to; int w; }Edges[25500]; int father[550],ans; int find(int x) { int root = x; while(root != father[root]) { root = father[root]; } int z; while(x != root) { z = father[x]; father[x] = root; x = z; } return root; } //bool cmp(Node a,Node b) //{ // return a.w < b.w; //} int cmp(const void * a, const void * b) { return ((Node *)a)->w - ((Node *)b)->w; } bool Kruskal(int N,int M,int k) { // sort(Edges,Edges+M,cmp); qsort(Edges,M,sizeof(Node),cmp); int x,y; for(int i = 0; i < M; i++) { x = find(Edges[i].from); y = find(Edges[i].to); if(x != y) { father[y] = x; k++; ans += Edges[i].w; if(k == N-1) return true; } } if(k == N-1) return true; else return false; } int main() { int T,k,t,a,b,N,M,K; scanf("%d",&T); while(T--) { scanf("%d%d%d",&N,&M,&K); for(int i = 1; i <= N; i++) father[i] = i; for(int i = 0; i < M; i++) { scanf("%d%d%d",&Edges[i].from,&Edges[i].to,&Edges[i].w); } k = 0,ans = 0; for(int i = 0; i < K; i++) { scanf("%d%d",&t,&a); a = find(a); t--; while(t--) { scanf("%d",&b); b = find(b); if(a != b) { father[b] = a; k++; } } } if(Kruskal(N,M,k)) printf("%d\n",ans); else printf("-1\n"); } return 0; }