题意:定义两点之间的距离为从一个点到另一个点经过的点数之和(包括这两个点),设二元组(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 树的直径的更多相关文章

  1. hdu 4607 Park Visit 求树的直径

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4607 题目大意:给你n个点,n-1条边,将图连成一棵生成树,问你从任意点为起点,走k(k<=n) ...

  2. HDU 2196.Computer 树形dp 树的直径

    Computer Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  3. Hdu 4612 Warm up (双连通分支+树的直径)

    题目链接: Hdu 4612 Warm up 题目描述: 给一个无向连通图,问加上一条边后,桥的数目最少会有几个? 解题思路: 题目描述很清楚,题目也很裸,就是一眼看穿怎么做的,先求出来双连通分量,然 ...

  4. hdu 4123 Bob’s Race 树的直径+rmq+尺取

    Bob’s Race Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Probl ...

  5. F - Warm up - hdu 4612(缩点+求树的直径)

    题意:有一个无向连通图,现在问添加一条边后最少还有几个桥 分析:先把图缩点,然后重构图为一棵树,求出来树的直径即可,不过注意会有重边,构树的时候注意一下 *********************** ...

  6. HDU 4123 Bob’s Race 树的直径+单调队列

    题意: 给定n个点的带边权树Q个询问. 以下n-1行给出树 以下Q行每行一个数字表示询问. 首先求出dp[N] :dp[i]表示i点距离树上最远点的距离 询问u, 表示求出 dp 数组中最长的连续序列 ...

  7. F - Warm up HDU - 4612 tarjan缩点 + 树的直径 + 对tajan的再次理解

    题目链接:https://vjudge.net/contest/67418#problem/F 题目大意:给你一个图,让你加一条边,使得原图中的桥尽可能的小.(谢谢梁学长的帮忙) 我对重边,tarja ...

  8. hdu 4679 Terrorist’s destroy 树的直径+dp

    题意:给你一棵树,每条边都有值W,然后问你去掉一条边,令val = w*max(两颗新树的直径),求val最小值~ 做法,先求树的直径,然后算出直径上每个点的最长枝条长度.这样对于每一条边,假如是枝条 ...

  9. HDU 4607 Park visit (求树的直径)

    解题思路: 通过两次DFS求树的直径,第一次以随意点作为起点,找到距离该点距离最远的点,则能够证明这个点一定在树的直径上,然后以该点为起点进行DFS得到的最长路就是树的直径. 最后的询问,假设K &l ...

随机推荐

  1. Conservation Vs Non-conservation Forms of conservation Equations

    What does it mean? The reason they are conservative or non-conservative has to do with the splitting ...

  2. Windows10下安装Jupyter

    打开cmd 升级pip3的版本: pip3 install --upgrade pip 安装Jupyter pip3 install jupyter

  3. P2627 修剪草坪 (单调队列优化$dp$)

    题目链接 Solution 70分很简单的DP,复杂度 O(NK). 方程如下: \[f[i][1]=max(f[j][0]+sum[i]-sum[j])\]\[f[i][0]=max(f[i-1][ ...

  4. 【CF1257F】Make Them Similar【meet in the middle+hash】

    题意:给定n个数,让你给出一个数,使得n个数与给出的数异或后得到的数的二进制表示中1的数量相同 题解:考虑暴搜2^30去找答案,显然不可接受 显然可以发现,这是一个经典的meet in the mid ...

  5. 《数据结构与算法(C语言版)》严蔚敏 | 第四章课本案例

    //二叉树的顺序存储表示 #define MAXTSIZE 100 typedef TElemtype SqBiTree[MAXTSIZE]; SqBiTree bt; //二叉树的二叉链表存储表示 ...

  6. python-zx笔记10-断言

    断言 断言内容是自动化脚本的重要内容,正确设置断言以后才能帮助我们判断测试用例执行结果. 断言方法 assertEqual(a, b) 判断a==b assertNotEqual(a, b) 判断a! ...

  7. win7系统开机启动出现蓝屏,提示BAD_SYSTEM_CONFIG_INFO

    因为我在msconfig->引导->高级选项中将最大内存勾选,最大内存勾选后是4096MB,但是在点击确定按钮后,会自动变成0MB(点击确定按钮后再点击高级选项),导致系统无法识别内存,开 ...

  8. AtCoder Grand Contest 012 B - Splatter Painting(dp)

    Time limit : 2sec / Memory limit : 256MB Score : 700 points Problem Statement Squid loves painting v ...

  9. EZOJ #389点分治好题

    分析 一层一层把叶子去掉 看最多能去掉多少层即可 代码 #include<bits/stdc++.h> using namespace std; ],du[],fa[],n,m,ans; ...

  10. day05—JavaScript之函数调用

    转行学开发,代码100天——2018-03-21 JavaScript中的函数调用有4种方式: 方式一:直接通过函数名调用 在 HTML 中默认的全局对象是 HTML 页面本身,所以函数是属于 HTM ...