Luogu 1111 修复公路

题目背景

A地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车。政府派人修复这些公路。

题目描述

给出A地区的村庄数N,和公路数M,公路是双向的。并告诉你每条公路的连着哪两个村庄,并告诉你什么时候能修完这条公路。问最早什么时候任意两个村庄能够通车,即最早什么时候任意两条村庄都存在至少一条修复完成的道路(可以由多条公路连成一条道路)

输入输出格式

输入格式:

第1行两个正整数N,M

下面M行,每行3个正整数x, y, t,告诉你这条公路连着x,y两个村庄,在时间t时能修复完成这条公路。

输出格式:

如果全部公路修复完毕仍然存在两个村庄无法通车,则输出-1,否则输出最早什么时候任意两个村庄能够通车。

输入输出样例

输入样例#1:
4 4
1 2 6
1 3 4
1 4 5
4 2 3
输出样例#1:
5

说明

N<=1000,M<=100000

x<=N,y<=N,t<=100000

(为什么一群人都在写生成树啊喂。。。明明带权并查集就行了啊。。。)

首先按照暴力来看,先把所有的道路按照时间排序,然后从小到大依次修改就行。

合并的时候需要在朴素并查集的基础上再维护当前集合的大小,开一个size数组扔给祖先就行了。

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <vector>
 7 
 8 using namespace std;
 9 
10 int n, m;
11 
12 struct STATE {
13     int x, y, t;
14 } st[110000];
15 
16 bool cmp(STATE a, STATE b) {
17     return a.t < b.t;
18 }
19 
20 int fa[110000], sz[110000];
21 
22 int get(int x) {
23     return x == fa[x] ? x : fa[x] = get(fa[x]);
24 }
25 
26 void merge(int x, int y) {
27     if(get(x) == get(y)) return;
28     sz[get(y)] += sz[get(x)];
29     fa[get(x)] = get(y);
30 }
31 
32 int main() {
33     scanf("%d%d", &n, &m);
34     for(int i = 1 ; i <= n ; i ++) fa[i] = i, sz[i] = 1;
35     for(int i = 1 ; i <= m ; i ++) {
36         scanf("%d%d%d", &st[i].x, &st[i].y, &st[i].t);
37     }
38     sort(st + 1, st + 1 + m, cmp);
39     for(int i = 1 ; i <= m ; i ++) {
40         merge(st[i].x, st[i].y);
41         if(sz[get(1)] == n) {
42             printf("%d\n", st[i].t);
43             break;
44         }
45     }
46     if(sz[get(1)] != n) puts("-1");
47 }
48         
View Code

 

 

posted @ 2017-08-10 09:46  KingSann  阅读(143)  评论(0编辑  收藏  举报