题面:[USACO18JAN]MooTube

题解:

对边和询问都排序,然后每次把符合当前要求的边都扔并查集里,对于每个询问判断当前并查集里节点数即可。

我很无聊地给并查集加了按秩排序,还开了O2,加了快读,也才170ms,虽然在第一面,然鹅还是没有办法排太前。

上述操作都不做也行

代码:

 #include<cstdio>
#include<algorithm>
using namespace std;
inline int rd(){
int x=; char c=getchar();
while(c<''||c>'')c=getchar();
while(c>=''&&c<=''){x=x*+c-''; c=getchar();}
return x;
}
const int maxn=1e5+,maxq=1e5+;
int N,Q,a,b,c,fa[maxn],dep[maxn],f1,f2,now,cnt[maxn],ans[maxq];
struct Edge{ int from,to,dis; }edge[maxn];
struct Query_{ int k,x,id; }qry[maxq];
inline bool cmp1(const Edge&a,const Edge&b){ return a.dis>b.dis; }
inline bool cmp2(const Query_&a,const Query_&b){ return a.k>b.k; }
inline int getf(int a){
if(fa[a]==a) return a;
fa[a]=getf(fa[a]);
return fa[a];
}
int main(){
scanf("%d%d",&N,&Q);
for(int i=;i<N;i++){
a=rd(); b=rd(); c=rd();
edge[i].from=a;
edge[i].to=b;
edge[i].dis=c;
}
for(int i=;i<=Q;i++){
a=rd(); b=rd();
qry[i].k=a; qry[i].x=b; qry[i].id=i;
}
sort(edge+,edge+N,cmp1);
sort(qry+,qry+Q+,cmp2);
for(int i=;i<=N;i++) fa[i]=i,cnt[i]=;
now=;
for(int i=;i<=Q;i++){
while(now+<=N- && edge[now+].dis>=qry[i].k){
now++;
f1=getf(edge[now].from);
f2=getf(edge[now].to);
if(f1!=f2){
if(dep[f1]<dep[f2]){
fa[f1]=f2;
cnt[f2]+=cnt[f1];
}
else if(dep[f1]>dep[f2]){
fa[f2]=f1;
cnt[f1]+=cnt[f2];
}
else{
fa[f1]=f2;
dep[f2]++;
cnt[f2]+=cnt[f1];
}
}
}
ans[qry[i].id]=cnt[getf(qry[i].x)]-;
}
for(int i=;i<=Q;i++) printf("%d\n",ans[i]);
return ;
}

By:AlenaNuna

05-28 14:35