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