並查集的一般操作 ①
阿新 • • 發佈:2018-01-12
flag get 能夠 clas tro lap clu oid operator
Rt
題目背景
A地區在地震過後,連接所有村莊的公路都造成了損壞而無法通車。政府派人修復這些公路。
題目描述
給出A地區的村莊數N,和公路數M,公路是雙向的。並告訴你每條公路的連著哪兩個村莊,並告訴你什麽時候能修完這條公路。問最早什麽時候任意兩個村莊能夠通車,即最早什麽時候任意兩條村莊都存在至少一條修復完成的道路(可以由多條公路連成一條道路)
輸入輸出格式
輸入格式:
第1行兩個正整數N,M
下面M行,每行3個正整數x, y, t,告訴你這條公路連著x,y兩個村莊,在時間t時能修復完成這條公路。
輸出格式:
如果全部公路修復完畢仍然存在兩個村莊無法通車,則輸出-1,否則輸出最早什麽時候任意兩個村莊能夠通車。
輸入:
4 4
1 2 6
1 3 4
1 4 5
4 2 3
輸出:
5
分析:
首先讀題發現是一道並查集的 水 題,先對t從小到大排序,然後挨個合並,但怎麽判斷合並全了?
這時我們需要一個很巧妙的方法
可以建一個val[ ]=1;然後集合合並時val相加
詳見代碼:
#include <cstdio> #include <algorithm> using namespace std; int n,m; int val[1000010]; //並查集 struct b { int par[1000100]; inline void ih(){for(int i=1;i<=n;++i) {par[i]=i;val[i]=1View Code;}} inline int f (int x){return par[x]=(par[x]==x)?x:f(par[x]);} inline int u (int x,int y) { val[f(x)]+=val[f(y)];//對祖先的val操作 par[f(y)]=f(x); } inline int get_val (int x) { return val[f(x)]; } }s; struct data { int x,y,t; friend bool operator< (data a,data b) { return a.t<b.t; } }a[10100000]; int sum=2,ans; bool flag=0; int main() { freopen("in","r",stdin); scanf("%d%d",&n,&m); scanf("%d%d%d",&a[0].x,&a[0].y,&a[0].t); for(int i=1;i<m;++i) { scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].t); } sort(a,a+m); s.ih(); for(int i=0;i<m;++i) { if(s.f(a[i].x)!=s.f(a[i].y)) { s.u(a[i].x,a[i].y); ans=a[i].t; if(s.get_val(a[i].x)==n) { printf("%d",ans); flag=1; break; } } } if(flag==0) { printf("-1"); } }
並查集的一般操作 ①