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 }

 

 

 

posted @ 2013-08-09 11:33  小の泽  阅读(153)  评论(0编辑  收藏  举报