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 }
时间: 2024-12-15 07:12:37

HDU 3371 Connect the Cities(并查集+Kruskal)的相关文章

hdu 3371 Connect the Cities

链接:hdu 3371 已知已连通的路的序号,以及未连通的路的费用,求将所有城市连通的最小费用 也是将已连通的路的费用记为0,就转化成了基本最小生成树的题 不过这题数组要开的大点,不然很容易就RE了... #include<cstdio> #include<algorithm> using namespace std; int f[510],n,m; struct stu { int a,b,c; }t[100000]; int cmp(struct stu x,struct st

hdu 3371 Connect the Cities(prim算法)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3371 Connect the Cities Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 13628    Accepted Submission(s): 3679 Problem Description In 2100, since

HDU 3371 Connect the Cities 【最小生成树,Prime算法+Kruskal算法】

Connect the Cities Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 17167    Accepted Submission(s): 4335 Problem Description In 2100, since the sea level rise, most of the cities disappear. Tho

hdu 3371 Connect the Cities Prim + Kruskal两种算法分别AC 水过~~~~

Connect the Cities Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 11727    Accepted Submission(s): 3278 Problem Description In 2100, since the sea level rise, most of the cities disappear. Tho

Hdu 3371 Connect the Cities(最小生成树)

地址:http://acm.hdu.edu.cn/showproblem.php?pid=3371 其实就是最小生成树,但是这其中有值得注意的地方:就是重边.题目没有告诉你两个城市之间只有一条路可走,所以两个城市之间可能有多条路可以走. 举例: 输入可以包含 1 2 3  // 1到2的成本为3   1 2 5  //1到2的成本为5      因此此时应选成本较低的路. 然后,已经连通的城市之间的连通成本为0. 这题用G++提交得到984ms的反馈,用C++提交则得到484ms的反馈. 很想知

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

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3371 题目不难 稍微注意一下 要把已经建好的城市之间的花费定义为0,在用普通Prim算法就可以了:我没有用克鲁斯卡尔算法(Kruskal's algorithm),因为这题数据比较大,而且要处理大量的数据使它为0,怕超时T^T..... 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 5 usi

HDU 2784 Connections between cities 并查集+Online_LCA

模板攒起来 #include <iostream> #include <algorithm> #include <cstdlib> #include <cstdio> #include <cstring> #include <queue> #include <stack> #pragma comment(linker, "/STACK:1024000000"); #define LL long long

hdu 3371 Connect the Cities 最小生成树

#include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <set> #include <map> #include <string> #include <ma

HDU 3635 延缓更新的并查集

Dragon Balls Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2839    Accepted Submission(s): 1097 Problem Description Five hundred years later, the number of dragon balls will increase unexpecte