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

原题链接: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.mfbz.cn/a/383155.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C语言分钟计算

一.题目描述 给你同一天的两个时间(24小时制),求这两个时间内有多少分钟,保证第一个时间在第二个时间之前. 二.输入描述 输入两行,每行包括两个整数表示小时和分钟. 三.输出描述 输出分钟数. 四.示例 输入 10 10 11 05 输出 55 五.代码

【Linux中增加Nginx虚拟主机配置文件(conf.d)】后访问80端报403

在nginx.conf的http模块新增 include /etc/nginx/conf.d/*.conf; 后 重启nginx报403 处理办法&#xff1a; 1&#xff0c;如果nginx是root用户启动的 则需要 将nginx.config的user改为和启动用户一致 2.权限问题&#xff0c;如果nginx没有web目录的操作权限&#xff0c;也会出…

《21天精通IPv4 to IPv6》第3天:IPv6地址配置——如何为不同的系统配置IPv6?

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

【报错解决】-bash: export: `-8‘: not a valid identifier 不是有效的标识符

现象 一登陆就提示-bash: export: -8’: not a valid identifier 不是有效的标识符 问题出现的原因 设置字符集时多写了空格 [rootdb1 ~]# cat >>/etc/profile<<EOF export LANGen_US.UTF -8(-8前不应有空格) EOF 解决方法 cd /etc vi profile 把export带有-8的…

c++求三个数中最大数

#include<iostream> using namespace std; int main() { int a,b,c; cout<<"请输入三个数字"<<endl;//end后面为小写的L cin>>a>>b>>c; if(a>b&&a>c) cout<<"最大数为a:"<<a<<e…

基于centos的Linux中如何安装python

前言 之前在linux上安装python的时候没来及记录下来&#xff0c;感觉还是有必要的&#xff0c;所以现在打算把原来装好的python卸载掉&#xff0c;然后重装一遍&#xff0c;重新记录一下。当前环境是否安装python 通过查询我发现机器里有3个版本的python&#xff0c;第一个是…

常用的git命令

1、git clone 克隆远程项目。从远程上下载的是master分支&#xff0c;通常开发都会重新拉一个分支&#xff0c;比如dev&#xff0c;在dev分支上进行开发&#xff0c;然后再合并到master上。 git clone http://xxxxxxxxxxxxxx.git2、git checkout 检出特定分支。项目clone完以后…

Java奠基】对象数组练习

目录 商品对象信息获取 商品对象信息输入 商品对象信息计算 商品对象信息统计 学生数据管理实现 商品对象信息获取 题目要求是这样的&#xff1a; 定义数组存储3个商品对象。 商品的属性&#xff1a;商品的id&#xff0c;名字&#xff0c;价格&#xff0c;库存。 创建三个…

EasyExcel动态列导出

测试代码地址&#xff1a;https://gitee.com/wangtianwen1996/cento-practice/tree/master/src/test/java/com/xiaobai/easyexcel/dynamiccolumn 官方文档&#xff1a;https://easyexcel.opensource.alibaba.com/docs/2.x/quickstart/write 一、实现方式 1、根据需要导出的列…

【安卓跨程序共享数据,探究ContentProvider】

ContentProvider主要用于在不同的应用程序之间实现数据共享的功能&#xff0c;它提供了一套完整的机制&#xff0c;允许一个程序访问另一个程序中的数据&#xff0c;同时还能保证被访问数据的安全性。 目前&#xff0c;使用ContentProvider是Android实现跨程序共享数据的标准方…

一个小而实用的 Python 包 pangu,实现在中文和半宽字符(字母、数字和符号)之间自动插入空格

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一个小巧的库&#xff0c;可以避免自己重新开发功能。利用 Python 包 pangu&#xff0c;可以轻松实现在 CJK&#xff08;中文、日文、韩文&#xff09;和半宽字符&#xff08;字母、数字和符号&#xf…

代码随想录|day 13

Day 13 又出去玩了 附上一个学习链接&#xff1a;https://www.geeksforgeeks.org 具体页面&#xff1a;Introduction to Binary Tree - Data Structure and Algorithm Tutorials - GeeksforGeeks 一、理论学习 今天是回顾了二叉树中最重要的操作 : 遍历二叉树。 我们可以将…

解决挂梯子 无法正常上网 的问题

方法&#xff1a; 打开 控制面板 &#x1f449; 网络和Internet &#x1f449; Internet选项 &#x1f449; 连接 &#x1f449; 局域网设置 &#x1f449; 代理服务器 &#x1f449; 取消选项 有问题可参考下图

flask+python企业产品订单管理系统938re

在设计中采用“自下而上”的思想&#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;那么说明其中两个加数的和与另一个加数为相反数则满足题意。所以可以得到…

[职场] 公安管理学就业方向及前景 #媒体#笔记#笔记

公安管理学就业方向及前景 公安管理学是中国普通高等学校本科专业。本专业文理兼收&#xff0c;学制4年&#xff0c;授予法学学士学位。本专业培养掌握马克思主义基本原理&#xff0c;政治坚定&#xff0c;坚持党和国家的路线、方针、政策&#xff0c;具有良好职业素养、科学素…

Python并发编程之多线程

前言 本文介绍并发编程中另一个重要的知识 - 线程。 线程介绍 我们知道一个程序的运行过程是一个进程&#xff0c;在操作系统中每个进程都有一个地址空间&#xff0c;而且每个进程默认有一个控制线程&#xff0c;打个比方&#xff0c;在一个车间中有很多原材料通过流水线加工…

基于查询模板的知识图谱问答系统

目录 前言1 知识图谱问答系统的两个核心问题1.1 问句的表示与语义理解1.2 知识库的映射和匹配 2 问答基本流程2.1 模板生成2.2 模板实例化2.3 查询排序和结果获取 3 模板自动生成3.1 quint方法3.2 对齐任务 4 基于查询模板的知识图谱问答系统优缺点4.1 系统的优点4.2 系统的缺点…

安全的接口访问策略

渗透测试 一、Token与签名 一般客户端和服务端的设计过程中&#xff0c;大部分分为有状态和无状态接口。 一般用户登录状态下&#xff0c;判断用户是否有权限或者能否请求接口&#xff0c;都是根据用户登录成功后&#xff0c;服务端授予的token进行控制的。 但并不是说有了tok…

机器学习:Softmax介绍及代码实现

Softmax原理 Softmax函数用于将分类结果归一化&#xff0c;形成一个概率分布。作用类似于二分类中的Sigmoid函数。 对于一个k维向量z&#xff0c;我们想把这个结果转换为一个k个类别的概率分布p(z)。softmax可以用于实现上述结果&#xff0c;具体计算公式为&#xff1a; 对于…