Codeforces Round #582 (Div. 3) G. Path Queries 题解(种类并查集+kruskal的思想)

题目链接

题目大意

给你一棵树,求有多少条简单路径(u,v),满足u到v这条路径上的最大值不超过k。q次查询。(u<v)

题目思路

我还以为是换根dp啥的,没想到居然是类似于kruskal的思想来解题。

将所有边按权值从小到大排序,查询值qi也从小到大排序。对于每次查询的值qi,将边权小于等于qi的边通过并查集合并在一起。对于合并后的联通块,每个联通块对答案的贡献为size×(size−1)2,所有联通块的贡献直接求和即可。所以每次合并两个节点时,先将这两个节点所在的联通块的贡献减去,再加上合并后的贡献即可。

代码

#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define debug printf("I am here\n");
using namespace std;
typedef long long ll;
const int maxn=2e5+5,mod=2147493647,inf=0x3f3f3f3f;
int n,m,fa[maxn],num[maxn];
ll sum,ans[maxn];
pair<int,int> q[maxn];
struct node{
    int v,u,w;
}e[maxn];
int findd(int x){
    return x==fa[x]?fa[x]:fa[x]=findd(fa[x]);
    //最开始写成这样t了,注意还要使fa[x]=findd(fa[x])
    //return fa[x]==x?x:findd(fa[x]);
}
void unite(int a,int b){
    int faa=findd(a),fab=findd(b);
    if(faa==fab) return ;
    sum+=1ll*num[faa]*num[fab];
    num[faa]+=num[fab];
    fa[fab]=faa;
}
bool cmp(node a,node b){
    return a.w<b.w;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        fa[i]=i;num[i]=1;
    }
    for(int i=1;i<=n-1;i++){
        scanf("%d%d%d",&e[i].v,&e[i].u,&e[i].w);
    }
    for(int i=1;i<=m;i++){
        scanf("%d",&q[i].fi);
        q[i].se=i;
    }
    sort(e+1,e+1+n-1,cmp);sort(q+1,q+1+m);
    int last=1;
    for(int i=1;i<=m;i++){
        for(int j=last;j<=n-1;j++){
            if(e[j].w<=q[i].fi){
                unite(e[j].v,e[j].u);
                last++;
            }else{
                break;
            }
        }
        ans[q[i].se]=sum;
    }
    for(int i=1;i<=m;i++){
        printf("%lld%c",ans[i],i==m?'\n':' ');
    }
    return 0;
}

参考链接:https://www.cnblogs.com/–Simon/p/11479662.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值