zoukankan      html  css  js  c++  java
  • codeforces1213G Path Queries 并查集

    题意

    给定n个结点的树,每条边有边权,有m个询问,每个询问给一个(q_i)输出树上有多少点对的简单路径上最大的边权不超过(q_i)

    分析

    用并查集维护点集,同时维护大小。

    将所有边按边权排序,考虑每次从小到大加边,图中经过当前边的所有路径一定是以当前边的边权为最大值的,用并查集维护下图中每个联通块的大小,经过当前边的路径数即为(sz[find(u)]*sz[find(v)])。然后前缀和一下就可以(O(1))询问了。

    Code

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define lson l,mid,p<<1
    #define rson mid+1,r,p<<1|1
    #define pb push_back
    #define ll long long
    using namespace std;
    const int inf=1e9;
    const int mod=1e9+7;
    const int maxn=2e5+10;
    int n,m;
    int f[maxn];
    ll ans[maxn],sz[maxn];
    int find(int k){
    	if(k==f[k]) return k;
    	else return f[k]=find(f[k]);
    }
    struct ppo{
    	int u,v,w;
    	bool operator<(const ppo &r) const{
    		return w<r.w;
    	}
    }a[maxn];
    int main(){
    	//ios::sync_with_stdio(false);
    	//freopen("in","r",stdin);
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++) f[i]=i,sz[i]=1;
    	for(int i=1;i<n;i++){
    		scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
    	}
    	sort(a+1,a+n);
    	for(int i=1;i<n;i++){
    		int rx=find(a[i].u),ry=find(a[i].v);
    		ans[a[i].w]+=sz[rx]*sz[ry];
    		f[rx]=ry;
    		sz[ry]+=sz[rx];
    	}
    	for(int i=1;i<=2e5;i++) ans[i]+=ans[i-1];
    	while(m--){
    		int x;scanf("%d",&x);
    		printf("%lld ",ans[x]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    .NET程序内存分析工具CLRProfiler的使用
    Hudson、Jenkins的node节点设置(分布式处理自动化测试用例)
    Ruby+watir不能定位新打开的窗口解决办法
    L邮政挂号信查询
    ruby读写txt文件
    Jenkins、Hudson安装、配置详细记录
    nagios原理(二)
    存储过程例子
    存储过程 插入明细表
    nagios原理(一)
  • 原文地址:https://www.cnblogs.com/xyq0220/p/11729564.html
Copyright © 2011-2022 走看看