树形DP CCPC威海-C. Rencontre

是我比较弱的图论题,比赛的时候没出.
传送门
题意:给定一棵树和三个集合,要求你从每个集合中任选一点,在得到三个点u,v,w后再在树上找到一个点r,使得dis(u,r)+dis(v,r)+dis(w,r)最小.
有一个结论是:这个点r一定在路径uv,vw,uw三个路径的交点上.
首先,可以确定的是,这三条路径一定会有交点,(因为是一棵树,树上的一个点到另一个点只有一条路径),当然这个交点唯一.
那么dis(u,r)+dis(v,r)+dis(w,r)=(dis(u,v)+dis(v,w)+dis(u,w))/2
有了这个结论后题目就变简单了:两个集合内各选一个点,计算出满足条件的任意点对的距离和.

三个集合两两枚举处理即可.
计算的时候有个技巧:考虑每条边对答案的贡献即可,即边的两边的属于集合a的元素和属于集合b的元素的数量统计一下即可进行运算.

#include<bits/stdc++.h>
using namespace std;
#define MAXN 200500
#define ll long long
vector<pair<int,ll>>e[MAXN];
ll cnt[MAXN];
int x[MAXN][3];
ll sz[MAXN][3];

long double ans=0;
void solve(int rt,int pre)
{
   
    for(auto it:e[rt]) {
   
        if (it.first == pre)continue;
        int so=it.first;
        solve(it.first,rt);
        ll now=sz[so][0]*(sz[1]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值