题目链接

传送门

题意

定义\(L(a,b)\)为结点\(a\)到结点\(b\)的路径上的结点数,问有种\(pair(L(a,b),L(c,d))\)取值,其中结点\(a\)到结点\(b\)的路径与结点\(c\)到结点\(d\)的路径没有交叉。

思路

我们很容易想到要想两条路径不交叉,那么\(a,b\)与\(c,d\)必定在两棵不同的子树中,假设第一棵子树的直径位\(L1\),第二棵子树的直径为\(L2\),那么我们可以得知\([1,L1]\)必定可以与\([1,L2]\)进行匹配,那么对于\([1,L1]\)中的每个数\(x\)可以和\([1,L2]\)中的每个数\(y\)构成满足题意的\(pair(x,y)\),此时\(x\)的贡献就是\(L 2\),由于不能重复,因此我们对每个长度可以匹配的方案取一个\(max\),最后加起来就是答案了。

最后本题的难点就变成了求断开每条链后产生的两棵子树的直径了。

我们定义\(dp[i][0]\)为以\(i\)为根节点的子树中以\(i\)为一个端点的最长距离,\(dp[i][1]\)为次远,\(dp[i][2]\)为第\(3\)远,那么这个子树的直径为\(max(\)以\(i\)为子树中不经过\(i\)的最长链,经过\(i\)的最长链\()\),\(dp[i][3]\)为\(i\)从其父亲结点往父亲的其他链能到达的最远距离,则断开\(i\)与其父亲的这条链生成的另一棵子树的直径就为\(max(\)不经过\(i\)的父亲结点的最长链,经过\(i\)的父亲结点的最长链\()\),具体转移请看代码。

代码

#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL; #define lson (rt<<1)
#define rson (rt<<1|1)
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("/home/dillonh/CLionProjects/Dillonh/in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0) const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 100000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL; int t, n, tot;
int head[maxn], dept[maxn], u[maxn], v[maxn], w[maxn];
int dp[maxn][5], L1[maxn], L2[maxn], ans[maxn], len[maxn][3]; struct edge {
int v, w, next;
}ed[maxn*2]; void add(int u, int v, int w) {
ed[tot].v = v;
ed[tot].w = w;
ed[tot].next = head[u];
head[u] = tot++;
} void dfs1(int u, int p, int d) {
dept[u] = d;
for(int i = head[u]; ~i; i = ed[i].next) {
int v = ed[i].v;
if(v == p) continue;
dfs1(v, u, d + 1);
int tmp = dp[v][0] + ed[i].w;
if(tmp > dp[u][0]) swap(tmp, dp[u][0]);
if(tmp > dp[u][1]) swap(tmp, dp[u][1]);
if(tmp > dp[u][2]) swap(tmp, dp[u][2]);
L1[u] = max(L1[u], L1[v]);
}
L1[u] = max(L1[u], dp[u][0] + dp[u][1]);
} void dfs2(int u, int p) {
len[u][0] = len[u][1] = 0;
for(int i = head[u]; ~i; i = ed[i].next) {
int v = ed[i].v;
if(v == p) continue;
int tmp = L1[v];
//处理不经过u的最长链
if(tmp > len[u][0]) swap(tmp, len[u][0]);
if(tmp > len[u][1]) swap(tmp, len[u][1]);
}
for(int i = head[u]; ~i; i = ed[i].next) {
int v = ed[i].v;
if(v == p) continue;
//经过u的最长链
if(dp[u][0] == dp[v][0] + ed[i].w) {
dp[v][3] = max(dp[u][3], dp[u][1]) + ed[i].w;
L2[v] = max(dp[u][3], dp[u][2]) + dp[u][1];
} else {
dp[v][3] = max(dp[u][3], dp[u][0]) + ed[i].w;
if(dp[u][1] == dp[v][0] + ed[i].w) {
L2[v] = max(dp[u][3], dp[u][2]) + dp[u][0];
} else {
L2[v] = max(dp[u][3], dp[u][1]) + dp[u][0];
}
}
//处理掉不经过u的最长链是否是由以v这棵子树贡献的情况
if(len[u][0] != L1[v]) L2[v] = max(L2[v], len[u][0]);
else L2[v] = max(L2[v], len[u][1]);
dfs2(v, u);
}
} int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
tot = 0;
for (int i = 1; i <= n; ++i) head[i] = -1, dp[i][0] = dp[i][1] = dp[i][2] = dp[i][3] = L1[i] = L2[i] = dept[i] = ans[i] = 0;
for (int i = 1; i < n; ++i) {
scanf("%d%d", &u[i], &v[i]);
add(u[i], v[i], 1), add(v[i], u[i], 1);
}
dfs1(1, 0, 0);
dfs2(1, 0);
for(int i = 1; i < n; ++i) {
int x = u[i], y = v[i];
if(dept[x] < dept[y]) swap(x, y);
//由于我保存的直径是路径上的边数,因此结点数要为边数+1
ans[L1[x] + 1] = max(ans[L1[x] + 1], L2[x] + 1);
ans[L2[x] + 1] = max(ans[L2[x] + 1], L1[x] + 1);
}
LL sum = 0;
for(int i = n; i >= 1; --i) {
ans[i] = max(ans[i], ans[i+1]);
sum += ans[i];
}
printf("%lld\n", sum);
}
return 0;
}

Rikka with Travels(2019年杭电多校第九场07题+HDU6686+树形dp)的更多相关文章

  1. 2019年杭电多校第二场 1008题Harmonious Army(HDU6598+最小割+建图)

    题目链接 传送门 题意 有\(n\)个士兵,要你给他们分配职业.有\(m\)对关系,对于某一对关系\(u,v\),如果同为勇士则总能力增加\(a\),同法师则增加\(c\),一个勇士一个法师增加\(\ ...

  2. 2019年杭电多校第二场 1012题Longest Subarray(HDU6602+线段树)

    题目链接 传送门 题意 要你找一个最长的区间使得区间内每一个数出现次数都大于等于\(K\). 思路 我们通过固定右端点考虑每个左端点的情况. 首先对于每个位置,我们用线段树来维护它作为\(C\)种元素 ...

  3. 2019年杭电多校第二场 1002题Beauty Of Unimodal Sequence(LIS+单调栈)

    题目链接 传送门 思路 首先我们对\(a\)正反各跑一边\(LIS\),记录每个位置在前一半的\(LIS\)中应该放的位置\(ans1[i]\),后一半的位置\(ans2[i]\). 对于字典序最小的 ...

  4. 2019年杭电多校第一场 1009题String(HDU6586+模拟+单调栈)

    题目链接 传送门 题意 给你一个字符串,要你构造一个长为\(k\)的子串使得每个字母出现的次数在\([L_i,R_i](0\leq i\leq26)\)间且字典序最小. 思路 做这种题目就是要保持思路 ...

  5. 2019年杭电多校第一场 1004题Vacation(HDU6581+数学)

    题目链接 传送门 题意 有\(n+1\)辆车要过红绿灯,告诉你车的长度.与红绿灯的起点(题目假设红绿灯始终为绿).车的最大速度,问你第\(0\)辆车(距离最远)车头到达红绿灯起点的时间是多少(每辆车最 ...

  6. 2019年杭电多校第一场 1002题Operation(HDU6579+线性基)

    题目链接 传送门 题意 初始时有\(n\)个数,现在有\(q\)次操作: 查询\([l,r]\)内选择一些数使得异或和最大: 在末尾加入一个数. 题目强制在线. 思路 对于\(i\)我们记录\([1, ...

  7. 2018 Multi-University Training Contest 9 杭电多校第九场 (有坑待补)

    咕咕咕了太久  多校博客直接从第三场跳到了第九场orz 见谅见谅(会补的!) 明明最后看下来是dp场 但是硬生生被我们做成了组合数专场…… 听说jls把我们用组合数做的题都用dp来了遍 这里只放了用组 ...

  8. Rikka with Game[技巧]----2019 杭电多校第九场:1005

      Rikka with Game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Othe ...

  9. 杭电多校第九场 hdu6424 Rikka with Time Complexity 数学

    Rikka with Time Complexity Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K ( ...

随机推荐

  1. requests--文件上传,文件下载

    文件上传 在做接口自动化的时候,有时需要上传文件,比如更改头像等等,在request里,通过files参数来上传 import requests base_url = 'http://httpbin. ...

  2. B1005 继续(3n+1)猜想 (25 分)

    一.技术总结 一个是注意输出格式,也就是末尾没有空格,这个解决方法一般是使用一个计数,然后打印输出一个就减少一个. 就是在使用数组时,要注意段错误,也就是数组开辟的是否够大. 如果可以的话,可以多设置 ...

  3. 新电脑安装操作系统一定要注意硬盘是否被bitlocker加密!

    新电脑安装操作系统一定要注意硬盘是否被bitlocker加密! 前段时间帮一MM的戴尔灵越14燃5488装机,购买不久的电脑,硬盘是被bitlocker加密的,鬼知道戴尔为什么这么过分.按照常规思路, ...

  4. curl 用法

    背景 linux上发起http请求 使用方法 # get请求 curl "http://jwen.me/" # 获取返回的信息头 curl -i "http://jwen ...

  5. JVM系列之五:垃圾回收

    . jdk1.7的堆内存 1. 堆(Java堆) 堆是java虚拟机所管理的内存中最大的一块内存区域,也是被各个线程共享的内存区域, 在JVM启动时创建,该内存区域存放了对象实例(包括基本类型的变量及 ...

  6. linux 内核参数tcp_max_syn_backlog对应的队列最小长度

    环境:centos7.4 内核版本3.10 内核参数net.ipv4.tcp_max_syn_backlog定义了处于SYN_RECV的TCP最大连接数,当处于SYN_RECV状态的TCP连接数超过t ...

  7. 插件油泼猴+脚本 for chrome 安装 - https://greasyfork.org/zh-CN

    http://chromecj.com/utilities/2018-09/1525.html 一.将 *.crx 改名为 *.zip 二.访问 chrome://flags/#extensions- ...

  8. linux服务器可以访问IP访问不了域名地址

    1.curl www.baidu.com报错,curl 183.232.231.173可以或者nslookup+域名,nslookup+IP2.这个是因为linux服务器没有配置DNS域名服务器地址导 ...

  9. 需要“jquery”ScriptResourceMapping。请添加一个名为 jquery (区分大小写)的 ScriptResourceMapping。

    问题: 该错误是因为应用程序需要jQuery,但是当前项目中并没有jQuery,或者存在jQuery但是程序不知道jQuery的存放路径. 解决方案: 一.下载jQuery,引入必要的jquery-X ...

  10. Oracle数据库触发器

    第一次写触发器,浪费了一个小时,少了一个;编译不通过 当A表有更新或插入数据时,则触发器执行向B表插入对应条件的数据1 CREATE OR REPLACE TRIGGER Test -- 触发器名称 ...