bzoj5188: [Usaco2018 Jan]MooTube (離線+並查集)
阿新 • • 發佈:2018-12-10
Problem
給定一棵樹,邊有邊權,定義兩點之間距離為兩點路徑上的最小值。 次詢問,每次詢問 ,問從 出發到達每個點時,距離大於等於 的點有多少個
Solution
將邊權、詢問中的 從大到小排序。 每次將邊連起來,並查集合並。 詢問中,與此點聯通的點的個數即為答案
Code
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 100010
int n,m,sz[N],fa[N],ans[N] ;
struct node{int x,y,z;}a[N],q[N];
inline bool cmp(node x,node y){return x.z>y.z;}
int find(int x){
if(fa[x]!=x) fa[x]=find(fa[x]);
return fa[x];
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) fa[i]=i,sz[i]=1;
for(int i=1;i<n;i++) scanf("%d%d%d",&a[ i].x,&a[i].y,&a[i].z);
for(int i=1;i<=m;i++) scanf("%d%d",&q[i].z,&q[i].x),q[i].y=i;
sort(a+1,a+n,cmp);sort(q+1,q+m+1,cmp);
int tmp=1;
for(int i=1;i<=m;i++){
while(tmp<n && a[tmp].z>=q[i].z){
int x=find(a[tmp].x),y=find(a[tmp].y) ;
if(x!=y) fa[x]=y,sz[y]+=sz[x];
tmp++;
}
ans[q[i].y]=sz[find(q[i].x)]-1;
}
for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
return 0;
}