HDU 6686 Rikka with Travels 树的直径
题意:定义两点之间的距离为从一个点到另一个点经过的点数之和(包括这两个点),设二元组(x, y)为两条不相交的路径,一条长度为x,一条长度为y,问二元组(x, y)出现了多少次?
思路:直接上jls的讲解:
基础直径练习题。
考虑判断 能不能出现。劼论:任意取树上的一条直径,那么如果 能出现,那么一定存在一 种方案使得直径的两端都被使用了。证明很简单:假设存在一个端点没有被使用,那么考虑两条直线的 四个端点 ,一定可以把一个端点给移动到直径的这个端点上,因为直径是树上长的路径,因 此这次移动一定不会减少路径的长度。
考虑对每一个长度 ,求可以满足的长的 ,这样所有小于等于 的值也都能被满足。考虑在直径上 计算这些值:第一种情况,直径的两端分属不同的路径,那么可以枚举直径的一个端点那条路径在直径 上的后一个点,那么这一条路径的大长度就是这个点到直径端点的距离加上这个点往直径外的大 延伸长度,另一条路径的大长度也可以类似地求,其中大延伸长度可以用一个 的 DFS 计算出 来。第二种情况是有一条路径就是这条直径,那么另一条路径就是这条直径之外的长路径长度,这个 只要把直径上的点都删了再求一遍直径就行。
总的时间复杂度为 O(n)。
代码:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 100010;
vector<int> G[maxn];
int mp[maxn], mx_dis[maxn], f[maxn],Mx[maxn];
bool v[maxn], v1[maxn];
int root, mx, now;
vector<int> a;
void add(int x, int y) {
G[x].push_back(y);
G[y].push_back(x);
}
void dfs(int x, int fa, int dis, bool flag) {
f[x] = fa;
v1[x] = flag;
if(dis > mx) {
mx = dis;
now = x;
}
for (auto y : G[x]) {
if(y == fa || v[y]) continue;
dfs(y, x, dis + 1, flag);
}
}
int dfs1(int x, int fa) {
int mx = 0;
for (auto y : G[x]) {
if(v[y] || y == fa) continue;
mx = max(mx, dfs1(y, x));
}
return mx + 1;
}
int main() {
int T, x, y, n;
// freopen("6686in.txt", "r", stdin);
// freopen("out1.txt", "w", stdout);
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
a.clear();
for (int i = 1; i <= n; i++)
G[i].clear();
for (int i = 1; i < n; i++) {
scanf("%d%d", &x, &y);
add(x, y);
}
for (int i = 1; i <= n; i++)
v[i] = v1[i] = mp[i] = f[i] = mx_dis[i] = 0;
root = 1, mx = 0;
dfs(root, 0, 1, 0);
root = now, mx = 0;
dfs(root, 0, 1, 0);
for (int i = now; i; i = f[i]) {
v[i] = 1;
a.push_back(i);
}
for (auto x : a) {
mx_dis[x] = dfs1(x, 0);
}
for (int i = 1; i <= n; i++) v1[i] = 0;
int tmp = 0;
for (int i = 1; i <= n; i++) {
if(v[i] == 0 && v1[i] == 0) {
now = mx = 0;
dfs(i, 0, 1, 0);
dfs(now, 0, 1, 1);
tmp = max(tmp, mx);
}
}
mp[a.size()] = tmp;
mp[tmp] = a.size();
Mx[a.size()] = 0;
for (int i = a.size() - 2; i >= 0; i--) {
Mx[i + 1] = max(Mx[i + 2], (int)a.size() - i - 2 + mx_dis[a[i + 1]]);
}
for (int i = 0; i < a.size() - 1; i++) {
int x = i + mx_dis[a[i]];
int y = Mx[i + 1];
mp[x] = max(mp[x], y);
mp[y] = max(mp[y], x);
}
LL ans = 0;
mx = 0;
for (int i = a.size(); i >= 1; i--) {
mx = max(mx, mp[i]);
ans += mx;
}
printf("%lld\n", ans);
}
}
HDU 6686 Rikka with Travels 树的直径的更多相关文章
- hdu 4607 Park Visit 求树的直径
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4607 题目大意:给你n个点,n-1条边,将图连成一棵生成树,问你从任意点为起点,走k(k<=n) ...
- HDU 2196.Computer 树形dp 树的直径
Computer Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- Hdu 4612 Warm up (双连通分支+树的直径)
题目链接: Hdu 4612 Warm up 题目描述: 给一个无向连通图,问加上一条边后,桥的数目最少会有几个? 解题思路: 题目描述很清楚,题目也很裸,就是一眼看穿怎么做的,先求出来双连通分量,然 ...
- hdu 4123 Bob’s Race 树的直径+rmq+尺取
Bob’s Race Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Probl ...
- F - Warm up - hdu 4612(缩点+求树的直径)
题意:有一个无向连通图,现在问添加一条边后最少还有几个桥 分析:先把图缩点,然后重构图为一棵树,求出来树的直径即可,不过注意会有重边,构树的时候注意一下 *********************** ...
- HDU 4123 Bob’s Race 树的直径+单调队列
题意: 给定n个点的带边权树Q个询问. 以下n-1行给出树 以下Q行每行一个数字表示询问. 首先求出dp[N] :dp[i]表示i点距离树上最远点的距离 询问u, 表示求出 dp 数组中最长的连续序列 ...
- F - Warm up HDU - 4612 tarjan缩点 + 树的直径 + 对tajan的再次理解
题目链接:https://vjudge.net/contest/67418#problem/F 题目大意:给你一个图,让你加一条边,使得原图中的桥尽可能的小.(谢谢梁学长的帮忙) 我对重边,tarja ...
- hdu 4679 Terrorist’s destroy 树的直径+dp
题意:给你一棵树,每条边都有值W,然后问你去掉一条边,令val = w*max(两颗新树的直径),求val最小值~ 做法,先求树的直径,然后算出直径上每个点的最长枝条长度.这样对于每一条边,假如是枝条 ...
- HDU 4607 Park visit (求树的直径)
解题思路: 通过两次DFS求树的直径,第一次以随意点作为起点,找到距离该点距离最远的点,则能够证明这个点一定在树的直径上,然后以该点为起点进行DFS得到的最长路就是树的直径. 最后的询问,假设K &l ...
随机推荐
- win8安装maven
1.下载并解压maven F:\maven\apache-maven-3.5.2 2. 设置环境变量 3. Path路径中添加maven的可执行文件目录(bin目录) 4.验证maven是否安装成功: ...
- 理解性能的奥秘——应用程序中慢,SSMS中快(4)收集解决参数嗅探问题的信息
---从计划缓存中直接获取查询计划和参数: ), ) SELECT @dbname = 'hydee_连锁', @procname = 'dbo.p_select_ware'; WITH baseda ...
- sqlserver备份和恢复-5
视图备份和恢复 备份 1. 2. 恢复 1. 2. 3.勾选覆盖现有数据库. 4. bat备份恢复 原文: https://www.cnblogs.com/lonelyxmas/p/7958649.h ...
- 区间查询异或最大值——cf1100F,hdu6579(线性基)
hdu6579 题意初始时有n个数,现在有q次操作: 查询[l,r]内选择一些数使得异或和最大:在末尾加入一个数.题目强制在线. 思路对于i我们记录[1,i]每个基底最靠近i的位置和这个位置的值,然后 ...
- 常用的Android关键词定位方法
1字符串,特征字 根据程序运行中出现的特征字词进行搜索,从而获取定位到程序的相关位置之中.以前用 得比较多,不过现在一般难以找到想要的关键词.有时候需要对特征字进行拆分来进行搜索.才 能获得一点提示. ...
- html基础与表格的理解·
1.静态网页与动态网页的区别:是否访问数据库 2.超文本:超文本是指超出文本的范围,可以插入声音视频,表格图片等 3.标记语言与网页结构:标记语言就是标签,网页结构包含<html>< ...
- Centos安装GD库
tar zxvf ncurses-5.6.tar.gz 进入目录 cd ncurses-5.6 生成 makefile文件,再进一步编译 ./configure --prefix=/usr --wit ...
- XML scriptlet 连接数据库
<%@ page language="java" contentType="text/html" pageEncoding="GBK" ...
- Python笔记(二十)_多态、组合
多态 对于函数中的变量,我们只需要知道它这个变量是什么类,无需确切地知道它的子类型,就可以放心地调用类的方法,而具体调用的这个方法是作用在父类对象还是子类对象上,由运行时该对象的确切类型决定,这就是多 ...
- STL之pair及其非成员函数make_pair()
std::pair是一个结构模板,提供了一种将两个异构对象存储为一个单元的方法. 定义于头文件 <utility> template< class T1, class T2 > ...