《算法竞赛·快冲300题》每日一题:“直径点对”

算法竞赛·快冲300题》将于2024年出版,是《算法竞赛》的辅助练习册。
所有题目放在自建的OJ New Online Judge。
用C/C++、Java、Python三种语言给出代码,以中低档题为主,适合入门、进阶。

文章目录

  • 题目描述
  • 题解
  • C++代码
  • Java代码
  • Python代码

直径点对” ,链接: http://oj.ecustacm.cn/problem.php?id=1736

题目描述

【题目描述】 给你一个n个节点的树,编号为1到n。求存在多少对节点<u,v>,使得u到v的距离等于这棵树的直径。
   树的直径:树上最远的两个点的距离
   树上两点的距离:两点之间边的数量
   <1,2>和<2,1>属于两对节点
【输入格式】 第一行为正整数n(n≤300000)。接下来n-1行,每行两个数字u和v,表示点u和点v之间存在边
【输出格式】 输出一个数字表示答案。
【输入样例】

4
1 2
1 3
1 4

【输出样例】

6

题解

   求树的直径有两种方法[ 《算法竞赛》,清华大学出版社,罗勇军、郭卫斌著,231页,“4.7.2 树的直径”。]:
   (1)做两次DFS,第一次求一个任意点的最远点s,第二次求s的最远点t,s和t之间的距离就是树的直径。
   (2)树形DP。算法不难,但是解释有点长,见《算法竞赛》233页的说明。请仔细理解如何用树形DP求树的直径。
   以上两种方法,算法复杂度都为O(n),即只对每个节点处理O(1)次。
   本题用这两种方法都能求解。下面用树形DP求树的直径,求直径的同时统计距离为直径的节点对数量。
【重点】 树形DP。

C++代码

   定义状态dp[],dp[u]表示从u出发的最长路径的长度,这条路径的终点是u的一个叶子节点。
   定义num[],num[u]表示从u出发的最长路径的数量。
   定义maxlen,表示直径的长度,k是经过直径的节点对数量。
   详细解释见代码的注释。如果仍然不能理解,可以把代码中与num[]和k有关的第8、20、22、23、26、28、29行删除,剩下的代码就是《算法竞赛》233页的树形DP求直径的模板。然后再加上num[]和k的代码并理解。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 300010;
vector<int>e[N];
int dp[N];                   //dp[u]:从u出发的最长路径
int num[N];                  //num[u]:从u出发的最长路径数量
ll maxlen = 0, k = 0;        //直径的长度maxlen,经过直径的节点对数量k
void dfs(int u, int fa){dp[u] = 0;num[u] = 1;for(auto v : e[u]){if(v == fa)  continue;dfs(v, u);                   //继续深入,回溯时带回算好的dp[v]int now = dp[v] + 1;         //从u出发,经过子节点v的最长路径if(now + dp[u] > maxlen){    //此时dp[u]是不经过v,而经过其他子节点的最长路径//now+dp[u]是经过u的最长路径maxlen = now + dp[u];    //更新maxlen为经过u的最长路径//此时u、v可能在树的直径上。比较所有的maxlen,最大的就是树的直径k = num[u] * num[v];  //计算k,这个k可能重新赋值}else if(now + dp[u] == maxlen)  //把此时的len看成树的直径,如果20行的k更新,这里也会重算k += num[u] * num[v];if(now > dp[u]){            //u经过v的路径更长dp[u] = now;            //更新dp[u]为经过v的路径num[u] = num[v];        //v更可能在直径上,把经过u的最长路径数量更新为经过v的数量}else if(now == dp[u])       //相等,这也是最长路径num[u] += num[v];}
}
int main(){int n;   scanf("%d", &n);for(int i = 1; i < n; i++){int u, v;    scanf("%d%d", &u, &v);e[u].push_back(v);  //加边e[v].push_back(u);}dfs(1, 0);cout << k * 2 << endl;        //按题意u-v和v-u不同,所以乘以2return 0;
}

Java代码

import java.util.*;
import java.io.*;public class Main {static FastReader scanner = new FastReader();static int N = 300010;static ArrayList<Integer>[] e = new ArrayList[N];static int[] dp = new int[N]; // dp[u]:从u出发的最长路径static int[] num = new int[N]; // num[u]:从u出发的最长路径数量static long maxlen = 0, k = 0; // 直径的长度maxlen,经过直径的节点对数量k public static void main(String[] args) throws IOException {         int n = scanner.nextInt();for (int i = 1; i <= n; i++)   e[i] = new ArrayList<>();        for (int i = 1; i < n; i++) {int u = scanner.nextInt();int v = scanner.nextInt();e[u].add(v); // 加边e[v].add(u);}dfs(1, 0);System.out.println(k * 2); // 按题意u-v和v-u不同,所以乘以2} public static void dfs(int u, int fa) {dp[u] = 0;num[u] = 1;for (int v : e[u]) {if (v == fa)  continue;dfs(v, u); // 继续深入,回溯时带回算好的dp[v]int now = dp[v] + 1; // 从u出发,经过子节点v的最长路径if (now + dp[u] > maxlen) { // 此时dp[u]是不经过v,而经过其他子节点的最长路径// now+dp[u]是经过u的最长路径maxlen = now + dp[u]; // 更新maxlen为经过u的最长路径// 此时u、v可能在树的直径上。比较所有的maxlen,最大的就是树的直径k = num[u] * num[v]; // 计算k,这个k可能重新赋值} else if (now + dp[u] == maxlen) 
// 把此时的len看成树的直径,如果34行的k更新,这里也会重算k += num[u] * num[v];if (now > dp[u]) { // u经过v的路径更长dp[u] = now; // 更新dp[u]为经过v的路径// v更可能在直径上,把经过u的最长路径数量更新为经过v的数量num[u] = num[v];} else if (now == dp[u]) // 相等,这也是最长路径num[u] += num[v];}} static class FastReader {BufferedReader br;StringTokenizer st; public FastReader() { br = new BufferedReader(new InputStreamReader(System.in));  }String next() {while (st == null || !st.hasMoreElements()) {try {st = new StringTokenizer(br.readLine());} catch (IOException e) { e.printStackTrace();}}return st.nextToken();} int nextInt() {  return Integer.parseInt(next()); } String nextLine() {String str = "";try { str = br.readLine();} catch (IOException e) { e.printStackTrace(); }return str;}}
}

Python代码

#pypy
from collections import defaultdict
import sys
sys.setrecursionlimit(300000)e = defaultdict(list)
dp = [0] * 300010
num = [0] * 300010
maxlen = 0
k = 0def dfs(u, fa):global maxlen, kdp[u] = 0num[u] = 1for v in e[u]:if v == fa:   continuedfs(v, u)now = dp[v] + 1if now + dp[u] > maxlen:maxlen = now + dp[u]k = num[u] * num[v]elif now + dp[u] == maxlen:  k += num[u] * num[v]if now > dp[u]:dp[u] = nownum[u] = num[v]elif now == dp[u]:  num[u] += num[v]n = int(input())
for i in range(1, n):u, v = map(int, input().split())e[u].append(v)e[v].append(u)dfs(1, 0)
print(k * 2)

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

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

相关文章

电视连续剧 ffmpeg 批量去掉片头片尾

思路&#xff1a; 一、用python获取每集的总时长 二、把每集的时间&#xff0c;拼接成想要的ffmpeg的剪切命令命令。 1、用python获取每集的总时长 1&#xff0c;安装moviepy库&#xff0c;直接安装太慢&#xff0c;换成国内的源 pip install moviepy -i http://mirrors.aliyu…

ES kibana 创建索引快速脚本

删除 DELETE my_test创建索引 创建自定义ngram分词器 PUT my_test {"settings": {"index.max_ngram_diff": "32","analysis": {"analyzer": {"code_analyzer": {"tokenizer": "code_tokenizer&q…

二轮平衡小车3:PID速度环

使用芯片&#xff1a;STM32 F103 C8T6 今日继续我的二路平衡小车开发之路&#xff0c;今日编写的是二轮平衡小车的PID速度环&#xff0c;我准备了纸飞机串口助手软件来辅助测试调节PID。 本文主要贴代码&#xff0c;之前的文章都有原理&#xff0c;代码中相应初始化驱动部分也…

纽扣电池/锂电池UN38.3安全检测报告

根据规章要求&#xff0c;航空公司和机场货物收运部门应对锂电池进行运输文件审查&#xff0c;重要的是每种型号的锂电池UN38.3安全检测报告。该报告可由的三方检测机构。如不能提供此项检测报告&#xff0c;将禁止锂电池进行航空运输. UN38.3包含产品&#xff1a;1、 锂电池2…

无涯教程-JavaScript - BESSELK函数

描述 BESSELK函数返回修改后的Bessel函数Kn(x),该函数等效于针对纯虚参判断的Bessel函数。 这些也称为双曲贝塞尔函数。 语法 BESSELK(X, N)争论 Argument描述Required/OptionalXThe value at which to evaluate the function.RequiredNThe order of the function. If n i…

Matlab进阶绘图第27期—水平双向堆叠图

在上一期文章中&#xff0c;分享了Matlab双向堆叠图的绘制方法&#xff1a; 进一步&#xff0c;再来看一下水平双向堆叠图的绘制方法&#xff08;由于Matlab中未收录水平双向堆叠图的绘制函数&#xff0c;因此需要大家自行设法解决&#xff09;。 先来看一下成品效果&#xff…

UI设计开发原则

一、一致性原则 坚持以用户体验为中心设计原则&#xff0c;界面直观、简洁&#xff0c;操作方便快捷&#xff0c;用户接触软件后对界面上对应的功能一目了然、不需要太多培训就可以方便使用本应用系统。 1、字体 保持字体及颜色一致&#xff0c;避免一套主题出现多个字体&am…

Java正常加锁但是没有起作用的问题(纪实)

概述 Redisson分布式锁&#xff0c;加锁代码完全正确&#xff0c;但是却没有起到锁的作用。 首先说明一下&#xff0c;这里的加锁代码是正确的&#xff0c;不存在因为加锁错误&#xff0c;锁失效的问题。那么锁是正常有效的&#xff0c;为什么没有起到锁的作用呢。下面先说一下…

等保测评--安全管理中心--测评方法

安全子类--系统管理 a) 应对系统管理员进行身份鉴别,只允许其通过特定的命令或操作界面进行系统管理操作,并对这些操作进行审计; 一、测评对象 提供集中系统管理功能的系统; 二、测评实施 1)应核查是否对系统管理员进行身份鉴别; 2)应核查是否仅允许系统管理员通过…

基于多设计模式下的同步异步日志系统

基于多设计模式下的同步&异步日志系统 代码链接&#xff1a;https://github.com/Janonez/Log_System 1. 项目介绍 本项目主要实现一个日志系统&#xff0c; 其主要支持以下功能&#xff1a; 支持多级别日志消息支持同步日志和异步日志支持可靠写入日志到标准输出、文件…

【Three.js】第二十一章 Physics 物理

介绍 物理是WebGL可以添加到项目体验中最酷的功能之一。人们喜欢真实物理感的物体&#xff0c;看到它们碰撞、倒塌、坠落和弹跳&#xff0c;就像我的作品集一样&#xff1a; https: //bruno-simon.com/ 有很多方法可以将物理功能添加到您的项目中&#xff0c;这取决于您想要实…

Python标准库sys

sys 模块主要负责与 Python 解释器进行交互&#xff0c;该模块提供了一系列用于控制 Python 运行环境的函数和变量。 函数和对象清单 对象名称 对象说明 sys.argv 命令行参数List&#xff0c;第一个元素是程序本身路径 sys.path 返回模块的搜索路径&#xff0c;初始化时…

如何使用 Python 多处理模块

在本文[1]中&#xff0c;我们将学习如何使用多处理模块中的特定 Python 类&#xff08;进程类&#xff09;。我将通过示例为您提供快速概述。 什么是多处理模块&#xff1f; 还有什么比从官方文档中提取模块更好的方式来描述模块呢&#xff1f; Multiprocessing 是一个使用类似…

区块链技术研究探讨

介绍 区块链技术是一种去中心化的分布式账本技术&#xff0c;它通过将数据存储在多个参与者之间的区块链网络中&#xff0c;确保数据的透明性、安全性和不可篡改性。以下是关于区块链技术的一些重要信息&#xff1a; 1、 工作原理&#xff1a;区块链是由一系列按时间顺序链接…

21.4 CSS 盒子模型

1. 边框样式 border-style属性: 指定元素的边框样式.常用属性值: - none: 无边框(默认值). - solid: 实线边框. - dotted: 点状边框. - dashed: 虚线边框. - double: 双线边框. - groove: 凹槽状边框. - ridge: 脊状边框. - inset: 内阴影边框. - outset: 外阴影边框.这些值可…

python内置类属性

class Person:"""这是一个类&#xff0c;功能是描述一个人的精神面貌与行为"""age 19def __init__(self, name):self.name namedef run(self):print("run")"""__dict__ : 类属性__bases__ : 类所有父类构成元组__doc…

使用SimPowerSystems并网光伏阵列研究(Simulink实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

随机流-RandomAccessFile

RandomAccessFile RandomAccessFile 基本操作案例 RandomAccessFile 基本操作 案例 import java.io.*;public class TestMain09 {public static void main(String[] args) throws Exception {insert("D:\\home\\product\\aa.txt",2,"ni");}public static…

C++:类和对象(二)

本文主要介绍&#xff1a;构造函数、析构函数、拷贝构造函数、赋值运算符重载、const成员函数、取地址及const取地址操作符重载。 目录 一、类的六个默认成员函数 二、构造函数 1.概念 2.特性 三、析构函数 1.概念 2.特性 四、拷贝构造函数 1.概念 2.特征 五、赋值…

TS编译选项

自动监控编译 tsc xxx.ts -w 在一个文件夹下&#xff0c;创建 tsconfig.json 文件&#xff0c;在用命令 tsc 就可以自动编译当前文件夹下的ts文件 tsconfig.json文件配置如下&#xff1a; {/*tsconfig.json 是ts编译器的配置文件&#xff0c;ts编译器可以根据它的信息来对代…