Acwing 5469. 有效点对【正难则反+巧妙选择根节点】

news2024/11/24 4:21:21

原题链接:https://www.acwing.com/problem/content/5472/

题目描述:

给定一个 n 个节点的无向树,节点编号 1∼n。

树上有两个不同的特殊点 x,y,对于树中的每一个点对 (u,v)(u≠v),如果从 u 到 v 的最短路径需要经过点 x 和点 y(路径的两个端点也算经过),且相对顺序上经过点 x,经过点 y,那么就称 (u,v) 是一个无效点对,否则就称 (u,v) 是一个有效点对。

请你计算树中有效点对的数量。

注意:

  1. (u,v) 和 (v,u) 是两个不同的点对。
  2. 有效点对必须满足 u≠v。

输入输出描述:

输入格式

第一行包含三个整数 n,x,y。

接下来 n−1 行,每行包含两个整数 a,b,表示点 a 和点 b 之间存在一条无向边。

输出格式

一个整数,表示有效点对的数量。

数据范围

前 3 个测试点满足 1≤n≤10。
所有测试点满足 1≤n≤3×10^5,1≤x,y≤n,x≠y,1≤a,b≤n,a≠b。

输入样例1:
3 1 3
1 2
2 3
输出样例1:
5
输入样例2:
3 1 3
1 2
1 3
输出样例2:
4

解题思路:

这个题目的关键就在于巧妙选择根结点方便计算,还有一个非常常用的方法就是正难则反,如果直接计算有效点对,显然存在多种情况,直接计算比较困难,这个时候就应该想到正难则反了,无效点对指的是先经过x点,再经过y点的路径,这个比较好计算,总的点对数为n*(n-1),只需要用总的点对数减去无效点对数就是有效点对数,下面画个图描述一下 ,如下图

我们考虑以x,y路径之间的点为根节点,同时让x在上面,那么就只会出现图1和图2这种情况了,就方便计算了。

对于图1,假设以x为根节点的子树中结点的个数是sizex,以y为根结点的子树中结点个数为sizey,那么这种形式的树中无效点对个数为sizex*sizey,那么有效点对个数就是n*(n-1)-sizex*sizey。

对于图2,可以认为是图1的一种特殊情况,需要特判一下,假设以y为根节点的子树大小为sizey,那么无效点对的起点是y子树中的某个点,无效点对的终点是y子树之外的任意一个点,那么无效点对的数目就是sizey*(n-sizey),那么有效点对的数目就是n*(n-1)-sizey*(n-sizey)。

对于图3,无效点对起点只能是y以及y以下的任意一个点,终点只能是x以及x以上的任意一个点,这个不是很好计算,我们可以以x,y路径上的某一个点为根节点,那么就可以避免图3这种情况,只需要考虑图1和图2这俩种情况即可,为了方便可以以y的父节点为根节点,那么就只需要考虑图1和图2这俩种情况了。

时间复杂度:O(n),n表示点数,因为边数为n-1。

空间复杂度:O(n)。

cpp代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;
typedef long long LL;

const int N=3e5+10,M=N*2;

int n,x,y;
int h[N],e[M],ne[M],idx;
int fa[N];
int sizex,sizey;

void add(int a,int b)
{
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

void dfs1(int u,int father)
{
    fa[u]=father;
    for(int i=h[u];i!=-1;i=ne[i])
    {
        int j=e[i];
        if(j==father)continue;
        dfs1(j,u);
    }
}

int dfs2(int u,int father)
{
    int res=1;
    for(int i=h[u];i!=-1;i=ne[i])
    {
        int j=e[i];
        if(j==father)continue;
        int d=dfs2(j,u);
        res+=d;
        if(j==x)sizex=d;
        if(j==y)sizey=d;
    }
    return res;
}
int main()
{
    cin>>n>>x>>y;
    memset(h,-1,sizeof h);
    for(int i=0;i<n-1;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v),add(v,u);
    }
    
    dfs1(x,-1);  //第一个dfs是为了让x在上面,y在下面减少需要讨论的情况
    dfs2(fa[y],-1);  //第二个dfs以x,y路径上的某一个点为根节点方便计算,为了方便,不妨以y的父节点为根节点
    
    if(fa[y]==x){  //图2情况
        cout<<(LL)n*(n-1)-(LL)sizey*(n-sizey);
    }else {  //图1情况
        cout<<(LL)n*(n-1)-(LL)sizex*sizey;
    }
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1445204.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【MySQL基础】:深入探索DQL数据库查询语言的精髓(上)

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; MySQL从入门到进阶 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言一. DQL1.1 基本语法1.2 基础查询1.3 条件查询1.3 聚合函数 &#x1f324;️ 全篇…

备战蓝桥杯---动态规划(理论基础)

目录 动态规划的概念&#xff1a; 解决多阶段决策过程最优化的一种方法 阶段&#xff1a; 状态&#xff1a; 决策&#xff1a; 策略&#xff1a; 状态转移方程&#xff1a; 适用的基本条件 1.具有相同的子问题 2.满足最优子结构 3.满足无后效性 动态规划的实现方式…

寻找最优的路测线 - 华为OD统一考试

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 200分 题解&#xff1a; Java / Python / C 题目描述 评估一个网络的信号质量&#xff0c;其中一个做法是将网络划分为栅格&#xff0c;然后对每个栅格的信号质量计算。 路测的时候&#xff0c;希望选择一条信号最好…

[leetcode] 33. 搜索旋转排序数组

文章目录 题目描述解题方法二分查找java代码复杂度分析 题目描述 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组…

防火墙安全策略及nat实验

要求一&#xff1a;生产区的设备在工作时间访问dmz区,仅可访问http服务器 要求二&#xff1a;办公区可以全天访问dmz区&#xff0c;其中10.0.2.20可以访问FTP服务器和HTTP服务器&#xff0c;10.0.2.10仅可以ping通10.0.3.10 要求三&#xff1a;办公区在访问服务器区时采用匿名认…

基于数据挖掘的微博事件分析与可视化大屏分析系统

设计原理&#xff0c;是指一个系统的设计由来&#xff0c;其将需求合理拆解成功能&#xff0c;抽象的描述系统的模块&#xff0c;以模块下的功能。功能模块化后&#xff0c;变成可组合、可拆解的单元&#xff0c;在设计时&#xff0c;会将所有信息分解存储在各个表中&#xff0…

使用C#快速创建一个非常实用的桌面应用程序

过节时和我年纪轻轻就一把年纪的弟弟张老二闲聊了许久&#xff0c;发现他对编程产生了一泡浓厚的兴趣&#xff0c;于是我就给他漏了一手C#&#xff0c;做了一个简单的适用于win-x64配置cpu的桌面应用程序。 步骤如下&#xff1a; 1.打开Visual Studio,点击新建项目&#xff0…

iOS AlDente 1.0自动防过充, 拯救电池健康度

经常玩iOS的朋友可能遇到过长时间过充导致的电池鼓包及健康度下降问题。MacOS上同样会出现该问题&#xff0c;笔者用了4年的MBP上周刚拿去修了&#xff0c;就是因为长期不拔电源的充电&#xff0c;开始还是电量一半的时候不接电源会黑屏无法开机&#xff0c;最后连着电源都无法…

【华为 ICT HCIA eNSP 习题汇总】——题目集12

1、企业网络内部常常采用私有 IP 地址进行通信&#xff0c;以下哪个地址属于私有 IP 地址&#xff1f; A、0.1.1.1 B、127.5.4.3 C、128.0.0.5 D、172.24.35.36 考点&#xff1a;网络层 解析&#xff1a;&#xff08;D&#xff09; A类 IP 地址中&#xff0c;10.0.0.0 ~ 10.255…

分享66个时间日期JS特效,总有一款适合您

分享66个时间日期JS特效&#xff0c;总有一款适合您 66个时间日期JS特效下载链接&#xff1a;https://pan.baidu.com/s/1niQUpDSs10gfGYKYnEgKRg?pwd8888 提取码&#xff1a;8888 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;…

【C语言初阶-结构体】关于结构体的声明定义、结构体传参详解

目录 1. 结构体的声明 1.1 结构的基础知识 1.2 结构的声明 1.3 结构成员的类型 1.4 结构体变量的定义和初始化 2. 结构体成员的访问 2.1(.)操作符 2.2&#xff08;->&#xff09;操作符 3.结构体传参 1. 结构体的声明 1.1 结构的基础知识 结构体是一些值的集合&…

前端JavaScript篇之异步编程的实现方式?

目录 异步编程的实现方式&#xff1f;1. 回调函数2. Promise3. Async/Await4. Generator 异步编程的实现方式&#xff1f; 异步编程是处理需要等待的操作的一种方式&#xff0c;比如读取文件、发送网络请求或处理大量数据。在JavaScript中&#xff0c;有几种常见的实现方式&am…

工业制造:分布式控制系统(DCS),一文掌握。

一、什么是DCS 在工业制造领域&#xff0c;DCS 是分布式控制系统&#xff08;Distributed Control System&#xff09;的缩写。DCS 是一种用于监控和控制工业生产过程的自动化系统&#xff0c;通常由一组分布在工厂各个位置的控制单元和计算机组成&#xff0c;用于实时监测和控…

面试经典150题——三数之和

​"The road to success and the road to failure are almost exactly the same." - Colin R. Davis 1. 题目描述 2. 题目分析与解析 2.1 思路一——暴力方法 因为三个数相加为0&#xff0c;那么说明其中两个加数的和与另一个加数为相反数则满足题意。所以可以得到…

QT入门-基本控件

1.QTextEdit qt助手查看可知一些信息,其余信息见全文 1.1 functions public function如下: 使用时通过QT助手查找 实例: #include "mainwindow.h" #include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new …

第73左侧菜单实现

layout下面新建menu layout index.vue导入menu import Menu from /views/layout/menu菜单实现&#xff1a; <template><el-menuactive-text-color"#ffd04b"background-color"#2d3a4b"class"el-menu-vertical-demo"default-active&quo…

apk反编译修改教程系列---简单修改apk默认横竖屏显示 手机端与电脑端同步演示【十一】

往期教程&#xff1a; apk反编译修改教程系列-----修改apk应用名称 任意修改名称 签名【一】 apk反编译修改教程系列-----任意修改apk版本号 版本名 防止自动更新【二】 apk反编译修改教程系列-----修改apk中的图片 任意更换apk桌面图片【三】 apk反编译修改教程系列---简单…

C语言 服务器编程-日志系统

日志系统的实现 引言最简单的日志类 demo按天日志分类和超行日志分类日志信息分级同步和异步两种写入方式 引言 日志系统是通过文件来记录项目的 调试信息&#xff0c;运行状态&#xff0c;访问记录&#xff0c;产生的警告和错误的一个系统&#xff0c;是项目中非常重要的一部…

02.数据结构

一、链表 作用&#xff1a;用于写邻接表&#xff1b; 邻接表作用&#xff1a;用于存储图或树&#xff1b; 1、用数组模拟单链表 #include<iostream> using namespace std;const int N 100010;// head 表示头结点的下标 // e[i] 表示结点i的值 // ne[i] 表示结点i的ne…

python适配器模式开发实践

1. 什么是适配器设计模式&#xff1f; 适配器&#xff08;Adapter&#xff09;设计模式是一种结构型设计模式&#xff0c;它允许接口不兼容的类之间进行合作。适配器模式充当两个不兼容接口之间的桥梁&#xff0c;使得它们可以一起工作&#xff0c;而无需修改它们的源代码。 …