Link:

USACO 2018 Jan Gold 传送门

A:

对于不同的$k$,发现限制就是小于$k$的边不能走

那么此时的答案就是由大于等于$k$的边形成的图中$v$所在的连通块除去$v$的大小

为了优化建图过程,考虑离线,将询问和边都按权值从大到小排序,依次加边即可

维护连通性和连通块大小用并查集

#include <bits/stdc++.h>

using namespace std;
#define X first
#define Y second
typedef long long ll;
typedef pair<int,int> P;
typedef double db;
const int MAXN=1e5+10;
struct query{int k,v,id;}qry[MAXN];
struct edge{int x,y,r;}e[MAXN<<2];
int n,q,f[MAXN],sz[MAXN],res[MAXN];

bool cmp1(edge a,edge b){return a.r>b.r;}
bool cmp2(query a,query b){return a.k>b.k;}

int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
void merge(int x,int y)
{
    int px=find(x),py=find(y);
    if(px==py) return;
    f[px]=py;sz[py]+=sz[px];
}

int main()
{
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++) 
        f[i]=i,sz[i]=1;
    for(int i=1;i<n;i++)
        scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].r);
    for(int i=1;i<=q;i++)
        scanf("%d%d",&qry[i].k,&qry[i].v),qry[i].id=i;
    sort(e+1,e+n,cmp1);sort(qry+1,qry+q+1,cmp2);    
    
    int top=1;
    for(int i=1;i<=q;i++)
    {
        while(e[top].r>=qry[i].k&&top<n)
            merge(e[top].x,e[top].y),top++;
        
        res[qry[i].id]=sz[find(qry[i].v)]-1;
    }
    for(int i=1;i<=q;i++)
        printf("%d\n",res[i]);
    return 0;
}
Problem A

相关文章: