hdu 3371 Connect the Cities
题目:
http://acm.hdu.edu.cn/showproblem.php?pid=3371
最小生成树,这题用Kruskal算法加并查集,对于已经连通的集合处理方式是把他们的根结点设为同一个。注意边的添加不能使最小生成树产生回路。
还有只能用C++交,用G++会超时啊~~~orz
源代码:
1 #include <iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 using namespace std; 5 //const int INF=100000000; 6 const int maxn=255003; 7 int road,ans,i,j,n,m,k; 8 int from[maxn],to[maxn],c[maxn],s[maxn]; //from to是城市 c是花费 用s进行排序 9 int fa[510]; //父结点 10 int cmp(const int a,const int b){ 11 return c[a]<c[b]; 12 } 13 int find(int x) 14 { 15 return fa[x]==x?x:fa[x]=find(fa[x]); 16 } 17 18 int kruskal(){ 19 road=0; 20 ans=0; 21 for(i=0;i<m;i++) 22 s[i]=i; 23 for(i=0;i<n;i++) 24 {if(fa[i]==i) road++;} 25 sort(s,s+m,cmp); 27 for(i=0;i<m&&road>1;i++){ //有n个根结点就要连n-1条路 29 int fa1=find(from[s[i]]); 30 int fa2=find(to[s[i]]); 31 if(fa1!=fa2){ 32 fa[fa1]=fa2; 33 road--; 34 ans+=c[s[i]]; 35 } 36 } 37 if(road==1) return ans; 38 return -1; 39 } 40 41 int main() 42 { 43 int cas; 44 scanf("%d",&cas); 45 while(cas--){ 47 scanf("%d %d %d",&n,&m,&k); 48 for(i=0;i<n;i++) 49 fa[i]=i; 50 for(i=0;i<m;i++){ 51 scanf("%d %d %d",&from[i],&to[i],&c[i]); 52 from[i]--; //城市我是从0开始记录,所以有-- 53 to[i]--; 54 } 55 for(i=0;i<k;i++){ 56 int t,temp_1,temp_2; 57 scanf("%d",&t); 58 scanf("%d",&temp_1); 59 temp_1--; 60 for(j=1;j<t;j++){ 61 scanf("%d",&temp_2); 62 temp_2--; 63 int fa1=find(temp_1); //不能直接把temp_2连到temp_1上啊,牢记血的教训 64 int fa2=find(temp_2); 65 //if(fa1!=fa2) //其实这个判断可以不用 66 fa[fa2]=fa1; 67 temp_1=temp_2; //其实这句也可以不要 68 69 } 70 } 71 ans= kruskal(); 73 printf("%d\n",ans); 74 } 75 return 0; 76 }