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 ...
随机推荐
- vsto c# 获取word里面的图片并保存
internal void GetEmbeddedImages() { ; Document doc = Globals.ThisAddIn.Application.ActiveDocument; f ...
- JavaScript 复杂判断的更优雅写法借鉴
前言: 我们编写js代码时经常遇到复杂逻辑判断的情况,通常大家可以用if/else或者switch来实现多个条件判断,但这样会有个问题,随着逻辑复杂度的增加,代码中的if/else/switch会变得 ...
- Centos7硬盘空间扩容(vmware虚拟机)
1. 查看系统挂载点 df -h 2. 系统关机 init 0 硬盘1空间修改为100G,保存并启动 3.查看磁盘 fdisk -l /dev/sda空间加上去了 3. 硬盘分区 fdisk /dev ...
- 10:基于Tomcat部署Web工程
1创建目录, 2.标识目录java文件,资源文件
- LintCode之合并排序数组II
题目描述: 分析:题目的意思是把数组A和数组B合并到数组A中,且数组A有足够的空间容纳A和B的元素,合并后的数组依然是有序的. 我的代码: public class Solution { /* * @ ...
- win10下VMware15运行ubuntu18.04无法和主机之间复制粘贴问题
可以运行以下命令行: sudo apt-get autoremove open-vm-tools sudo apt-get install open-vm-tools sudo apt-get ins ...
- jmeter(二十):Logic Controller:逻辑控制器(上)
逻辑控制器用来控制采样器(samplers)的执行顺序,根据实际需要定制执行规则.在控制器层级下面的所有的采样器都会当做一个整体,执行时也会一起被执行. Logic Controller种类: 以上L ...
- loj6259「CodePlus 2017 12 月赛」白金元首与独舞
分析 我们将没连的点连向周围四个点 其余的按照给定的方向连 我们将所有连出去的位置统一连到0点上 再以0作为树根 于是就将问题转化为了有向图内向树计数 代码 #include<iostream& ...
- 136、TensorFlow的Embedding lookup
import tensorflow as tf; import numpy as np; c = np.random.random([10, 1]) b = tf.nn.embedding_looku ...
- Flask-SQLALchemy动态的filter_by和filter
1.filter_by filter_by用于查询简单的列名,不支持比较运算符. filters = {'name': 'fengyao', 'age': 26} User.query.filter_ ...