码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 3371 Connect the Cities(并查集+Kruskal)

时间:2017-08-04 21:34:11      阅读:123      评论:0      收藏:0      [点我收藏+]

标签:oid   logs   end   ring   cto   保留   amp   ++   problem   

题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=3371

思路:

这道题很明显是一道最小生成树的题目,有点意思的是,它事先已经让几个点联通了。正是因为它先联通了几个点,所以为了判断连通性 很容易想到用并查集+kruskal。

不过要注意 这题有一个坑点,就是边数很多 上限是25000,排序的话可能就超时了。而点数则比较少 上限是500,所以很多人选择用Prim做。但我个人觉得这样连通性不好判断。其实边数多没关系,我们主要去重就好啦,用邻接矩阵存下两点间的最小权重 再排序即可,这样就不会超时啦~

 

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <vector>
 4 #include <algorithm>
 5 using namespace std;
 6 const int inf=1e5;
 7 struct node{
 8     int v,u,w;
 9     bool operator <(const node &x) const{
10         return w<x.w;
11     }
12 };
13 int pre[505];
14 int mp[505][505];
15 int n,m,k;
16 int cnt;
17 vector<node>v;
18 void init(){
19     for(int i=1;i<=n;i++){
20         pre[i]=i;
21         for (int j=1; j<=n; j++) {
22             mp[i][j]=inf;
23         }
24     }
25 }
26 int query(int x){
27     int r=x;
28     while (pre[x]!=x) {
29         x=pre[x];
30     }
31     pre[r]=x;
32     return x;
33 }
34 bool join(int x,int y){
35     int fx=query(x);
36     int fy=query(y);
37     if(fx!=fy){
38         pre[fx]=fy;
39         return true;
40     }
41     return false;
42 }
43 int kruskal(){
44     int res=0;
45     for(int i=0;i<v.size();i++){
46         if(join(v[i].v, v[i].u)){
47             res+=v[i].w;
48         }
49     }
50     return res;
51 }
52 int main(){
53     int t;
54     int res;
55     scanf("%d",&t);
56     while (t--) {
57         cnt=0;
58         v.clear();
59         scanf("%d%d%d",&n,&m,&k);
60         init();
61         for (int i=0; i<m; i++) {
62             int v,u,w;
63             scanf("%d%d%d",&v,&u,&w);
64             mp[v][u]=min(mp[v][u],w);//保留最小权重
65         }
66         for (int i=0; i<k; i++) {
67             int num,a,b;
68             scanf("%d",&num);
69             if(num) scanf("%d",&a);
70             for (int j=1; j<num; j++) {
71                 scanf("%d",&b);
72                 join(a, b);
73             }
74         }
75         for (int i=1; i<=n; i++) {
76             for (int j=1; j<=n; j++) {
77                 if(mp[i][j]==inf || i==j)   continue;
78                 v.push_back({i,j,mp[i][j]});//重新导入边,去掉了重复部分
79             }
80         }
81         sort(v.begin(), v.end());
82         res=kruskal();
83         for (int i=1; i<=n; i++) {
84             if(pre[i]==i)   cnt++;//算连通块个数
85         }
86         if(cnt==1)  printf("%d\n",res);
87         else printf("-1\n");
88     }
89 }

 

HDU 3371 Connect the Cities(并查集+Kruskal)

标签:oid   logs   end   ring   cto   保留   amp   ++   problem   

原文地址:http://www.cnblogs.com/uniles/p/7287076.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!