zoukankan      html  css  js  c++  java
  • 「BZOJ 5188」「Usaco2018 Jan」MooTube

    题目链接

    luogu
    bzoj

    (Describe)

    有一个(n)个节点的树,边有权值,定义两个节点之间的距离为两点之间的路径上的最小边权
    给你(Q)个询问,问你与点(v)的距离大于等于(k)的点有多少个

    (Solution)

    这道题主要用并查集搞一下就好了啊.

    离线的做.

    • 首先将边按照权值排序,将询问的按照k排序
    • 然后把权值大于等于(k)的放入并查集中,维护一个(siz)即节点的个数.

    (End)

    (Code)

    #include<bits/stdc++.h>
    #define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
    #define rg register
    using namespace std;
    typedef long long ll;
    int read(){
        int x=0,f=1;
    	char c=getchar();
        while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
        while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
        return f*x;
    }
    struct node{
    	int x,y,v;
    }a[100010],b[100010];
    int q[100010],pre[100010],siz[100010];
    bool cmp(const node & a , const node & b){
    	return a.v>b.v;
    }
    int find(int x){
    	return pre[x]==x?x:pre[x]=find(pre[x]);
    }
    void join(int x,int y){
    	int fx=find(x),fy=find(y);
    	if(fx!=fy)
    		pre[fx]=fy,siz[fy]+=siz[fx];
    }
    int main(){
    	int n=read(),m=read(),cnt=1;
    	for(int i=1;i<n;i++)
    		a[i].x=read(),a[i].y=read(),a[i].v=read(),pre[i]=i,siz[i]=1;
    	sort(a+1,a+n,cmp),pre[n]=n,siz[n]=1;
    	for(int i=1;i<=m;i++)
    		b[i].v=read(),b[i].x=read(),b[i].y=i;
    	sort(b+1,b+1+m,cmp);
    	for(int i=1;i<=m;i++){
    		while(a[cnt].v>=b[i].v)
    			join(a[cnt].x,a[cnt].y),cnt++;
    		q[b[i].y]=siz[find(b[i].x)]-1;
    	}
    	for(int i=1;i<=m;i++)
    		printf("%d
    ",q[i]);
    }
    
    
  • 相关阅读:
    面试题:最小的K个数
    面试题:反转链表
    面试题:二进制中1的个数
    数据结构之二叉树
    Serializable-源码分析
    归并、希尔、快速排序
    栈与队列
    简单排序(冒泡、选择、插入)
    Shiro 框架认证和授权
    mybatis select查询使用返回结果为resultMap
  • 原文地址:https://www.cnblogs.com/hbxblog/p/10312584.html
Copyright © 2011-2022 走看看