当前位置: 首页 > article >正文

CF1060E Sergey and Subway

CF1060E Sergey and Subway

树上计数dp,考虑每条边的贡献,树上两点距离用深度与LCA表示

长度为2的两点间可以连一条边,所以对于任意两点 i , j i,j i,j d i s 2 i , j = ⌈ d i s i , j / 2 ⌉ = ( d i s i , j + ( d i s i , j % 2 = = 1 ) ) / 2 dis2_{i,j}=\lceil dis_{i,j}/2 \rceil=(dis_{i,j}+ (dis_{i,j}\%2==1) )/2 dis2i,j=disi,j/2=(disi,j+(disi,j%2==1))/2
对于前半部分,我们要求原图上所有点对的距离,通过树形dp计算每条边对两端点集的贡献即可
对于后半部分,我们只需另外统计一下在原图中两点距离为奇数的点即可,对于任意两点: d i s i , j = d e p i + d e p j − 2 ∗ L C A i , j dis_{i,j}=dep_i+dep_j-2*LCA_{i,j} disi,j=depi+depj2LCAi,j 显然式子中的2*LCA不对奇偶产生影响,所以只需要处理出各点深度即可

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int n;
    cin>>n;
    vector<vector<int>> e(n+1);
    for (int i=1;i<n;i++){
        int a,b;
        cin>>a>>b;
        e[a].push_back(b);
        e[b].push_back(a);
    }

    vector<int> dep(n+1);
    vector<ll> sz(n+1);
    ll ans=0,cnt=0;
    function<void(int,int)> dfs=[&](int u,int fa){
        sz[u]=1;
        for (auto v:e[u]){
            if (v==fa) continue;
            dep[v]=dep[u]+1;
            dfs(v,u);
            sz[u]+=sz[v];
        }
        cnt+=(dep[u]%2==1);
        ans+=sz[u]*(n-sz[u]);
    };

    dep[1]=1;
    dfs(1,-1);
    cout<<(ans+cnt*(n-cnt))/2;
    return 0;
}

http://www.kler.cn/a/16713.html

相关文章:

  • 如何保护 Microsoft 网络免受中间人攻击
  • 高效稳定!新加坡服务器托管方案助力企业全球化布局
  • Postman上传图片如何处理
  • 建筑施工特种作业人员安全生产知识试题
  • 远离生成式AI大乱斗,SAS公司揭示亚太区千亿AI市场蓝图
  • 蓝桥杯每日真题 - 第7天
  • 并发编程之Atomic原子操作类
  • 【华为OD机试真题】计算网络信号 (javaC++python)100%通过率 超详细代码注释
  • 【计算机视觉】ViT:代码逐行解读
  • linux入门---软硬链接
  • 支持轴体热插拔的平价机械键盘,全尺寸带灯效,雷柏V700DIY上手
  • linux 设置开机启动不同方式
  • Linux系统中查看日志的命令
  • CentOS软件那么老为什么大家还要用它?
  • 为什么在马云成功前就有那么多影像留下来?
  • SpringBoot调取OpenAi接口实现ChatGpt功能
  • rac部署前配置互信
  • CUDA编程(六):代码分析与调试
  • 死信队列
  • Vue3透传Attributes
  • Crowdsoure的简单介绍
  • Android Signal 使用
  • 关于使用Notion的board做工作安排这件事
  • 『Linux』第九讲:Linux多线程详解(一)_ 线程概念 | 线程控制之线程创建 | 虚拟地址到物理地址的转换
  • 云原生技术概谈
  • 医院安全(不良)事件报告系统 PHP语言实现