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

Posted ventricle

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 3371 Connect the Cities(并查集+Kruskal)相关的知识,希望对你有一定的参考价值。

题目网址: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)的主要内容,如果未能解决你的问题,请参考以下文章

hdu3371 Connect the Cities (MST)

hdu-3371 Connect the Cities---kruskal

hdu oj 3371 Connect the Cities (最小生成树)

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

D - Connect the Cities (HDU - 3371)

POJ:3371 Connect the Cities(最小生成树)