首页 > 其他 > 详细

【USACO18JAN】MooTube G

时间:2020-05-19 17:12:56      阅读:109      评论:0      收藏:0      [点我收藏+]

题目链接

如果在第$i$个询问时,图上没有边权小于$k_i$的边,那么答案就是$v_i$所在连通块的大小减一。

那么可以先将询问按$k_i$降序排序,将边按边权降序排序。

这样每次询问之前,把边权不小于$k_i$的边用并查集并上即可。

 

代码(100分):

技术分享图片
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define IL inline
#define RG register
#define _1 first
#define _2 second
using namespace std;
const int N=1e5;

    int n,m;
    
struct Edge{
    int u,v,w;
}e[N+3];
    int p;
    
IL bool operator<(Edge a,Edge b){
    return a.w>b.w;
}

struct Qry{
    int k,v,d;
}q[N+3];
    
IL bool operator<(Qry a,Qry b){
    return a.k>b.k;
}

    int f[N+3],sz[N+3],c[N+3];

int find(int x){
    return f[x]==x?x:f[x]=find(f[x]);
}

IL void merge(int x,int y){
    if(sz[x]<sz[y])
        swap(x,y);
        
    f[y]=x;
    sz[x]+=(sz[x]==sz[y]);
    c[x]+=c[y];
    
}

    int ans[N+3];

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<n;i++)
        scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&q[i].k,&q[i].v);
        q[i].d=i;
    }
    
    sort(e+1,e+n);
    sort(q+1,q+m+1);
    p=1;
    for(int i=1;i<=n;i++){
        f[i]=i;    sz[i]=c[i]=1;
    }
    for(int i=1;i<=m;i++){
        for(;e[p].w>=q[i].k;p++)
            merge(find(e[p].u),find(e[p].v));
        ans[q[i].d]=c[find(q[i].v)]-1;
        
    }
    
    for(int i=1;i<=m;i++)
        printf("%d\n",ans[i]);

    return 0;

}
View Code

 

【USACO18JAN】MooTube G

原文:https://www.cnblogs.com/Hansue/p/12917850.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!