【树形dp 最长链】bzoj1912: [Apio2010]patrol 巡逻
富有思维性的树形dp
Description
Input
Output
Sample Input
1 2
3 1
3 4
5 3
7 5
8 5
5 6
Sample Output
HINT
10%的数据中,n ≤ 1000, K = 1;
30%的数据中,K = 1;
80%的数据中,每个村庄相邻的村庄数不超过 25;
90%的数据中,每个村庄相邻的村庄数不超过 150;
100%的数据中,3 ≤ n ≤ 100,000, 1 ≤ K ≤ 2。
题目分析
初看这题觉得毫无头绪,好像怎么也不能把它和最长链联系在一起。特别是新建的边必须经过一次的限制,让人一脸懵逼。
k=0
不过首先挖掘性质:显然的是,若只是树形图,路径最短为$2n-2$;并且实际上起点任意对于答案来说都是一样的。
k=1
然后我们来想一想$k=1$的情况。比如现在我们有一颗树长成这样:
然后我们现在添加一条边:
可以发现形成的环上,若环长度为$lens$,那么需要经过的路径就从$2*lens$变为了$lens+1$。并且对于其他节点来说,它们的花费是不改变的。
由此自然想到我们将最长链的首尾相连,就可以得到$k=1$时的答案。
k=2
有了k=1,扩展至k=2的思路大致相同。除了最长链形成的环,我们需要在树上另找一条次长链。
这里有一个技巧就是把最长链上的边权全都改为-1.引用CQzhangyu的一段话:
一开始想的是将直径拎出来,然后跑一个非常复杂的树形DP,但是看了题解。。。直接将直径上的所有边权值设为-1,再求一遍直径即可。正确性如何保证?如果这两条路径不相交,显然正确;如果相交,那么相当于将原路径拆成了两条。所以做法还是很巧妙的~
还有Coco_T的另一段话:
如果我们什么处理都没有,直接求一个次长链(次短路方法),
可能会和最长链重合,那么最长链上的一部分就会走两遍
所以我们在求出最长链之后,把最长链上的边权赋为-1,
这样再跑一个裸的直径就好了
(这样就可以保证可以在新求出的直径中尽量少重合原先的直径)
其实感觉能够感性理解,但是好像依旧不甚明白……?
还有要注意的是:
if (k==){
mx = ;
for (int i=s1[dir]; i!=-; i=s1[edges[i].y])
edges[i].val = edges[i^].val = -;
for (int i=s2[dir]; i!=-1; i=s1[edges[i].y])
edges[i].val = edges[i^].val = -;
dfs(, );
ans = ans-mx+;
}
这里第二部分的作用是,将dir的次长链的边权赋为-1.乍一眼看上去好像应该是for (int i=s2[dir]; i!=-1; i=s1[edges[i].y]),不过实际上次长链除了头上是s2,后面的路径走的都是其最大值。
#include<bits/stdc++.h>
const int maxn = ; struct Edge
{
int y,val;
Edge(int a=, int b=):y(a),val(b) {}
}edges[maxn<<];
int n,k,mx,dir,ans;
int edgeTot,nxt[maxn<<],head[maxn];
int s1[maxn],s2[maxn]; int read()
{
char ch = getchar();
int num = ;
bool fl = ;
for (; !isdigit(ch); ch = getchar())
if (ch=='-') fl = ;
for (; isdigit(ch); ch = getchar())
num = (num<<)+(num<<)+ch-;
if (fl) num = -num;
return num;
}
void addedge(int u, int v)
{
edges[++edgeTot] = Edge(v, ), nxt[edgeTot] = head[u], head[u] = edgeTot;
edges[++edgeTot] = Edge(u, ), nxt[edgeTot] = head[v], head[v] = edgeTot;
}
int dfs(int now, int fa)
{
int mx1 = , mx2 = ;
for (int i=head[now]; i!=-; i=nxt[i])
if (edges[i].y!=fa){
int tt = dfs(edges[i].y, now)+edges[i].val;
if (tt > mx1)
mx2 = mx1, mx1 = tt, s2[now] = s1[now], s1[now] = i;
else if (tt > mx2) mx2 = tt, s2[now] = i;
}
if (mx1+mx2 > mx) mx = mx1+mx2, dir = now;
return mx1;
}
int main()
{
memset(head, -, sizeof head);
memset(s1, -, sizeof s1);
memset(s2, -, sizeof s2);
n = read(), k = read();
for (int i=; i<n; i++)
addedge(read(), read());
dfs(, );
ans = *n-mx-;
if (k==){
mx = ;
for (int i=s1[dir]; i!=-; i=s1[edges[i].y])
edges[i].val = edges[i^].val = -;
for (int i=s2[dir]; i!=-; i=s1[edges[i].y])
edges[i].val = edges[i^].val = -;
dfs(, );
ans = ans-mx+;
}
printf("%d\n",ans);
return ;
}
END
【树形dp 最长链】bzoj1912: [Apio2010]patrol 巡逻的更多相关文章
- P3565 由简单的树形dp 引入 长链刨分
这道题感觉不太行 因为自己没想出来. 先说一下暴力吧,取三个点 让两两之间的距离相等怎么做呢,看起来是很复杂的样子的,但是仔细观察发现 答案出自一个点的儿子之间 或者儿子和父亲之间. 暴力枚举三个点然 ...
- LOJ3053 十二省联考2019 希望 容斥、树形DP、长链剖分
传送门 官方题解其实讲的挺清楚了,就是锅有点多-- 一些有启发性的部分分 L=N 一个经典(反正我是不会)的容斥:最后的答案=对于每个点能够以它作为集合点的方案数-对于每条边能够以其两个端点作为集合点 ...
- BZOJ1912 [Apio2010]patrol 巡逻
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...
- 2018.11.06 bzoj1912: [Apio2010]patrol 巡逻(树形dp)
传送门 一道挺妙的题啊. 对于K==1K==1K==1的直接求树的直径. 对于K==2K==2K==2的先求一次直径,然后考虑到如果两条边加进去形成的两个环重叠就会有负的贡献. 因此把之前那条直径上的 ...
- BZOJ1912:[APIO2010]patrol巡逻
Description Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2).接下来 n – 1行,每行两个整数 a, b, 表示村庄a与b之间有一条道路(1 ≤ a, b ≤ n). Ou ...
- 【BZOJ1912】[Apio2010]patrol 巡逻 树形DP
[BZOJ1912][Apio2010]patrol 巡逻 Description Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2).接下来 n – 1行,每行两个整数 a, b, 表示 ...
- 【BZOJ-1912】patrol巡逻 树的直径 + DFS(树形DP)
1912: [Apio2010]patrol 巡逻 Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 1034 Solved: 562[Submit][St ...
- [Apio2010]patrol 巡逻
1912: [Apio2010]patrol 巡逻 Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 2541 Solved: 1288[Submit][S ...
- BZOJ 1912:[Apio2010]patrol 巡逻(树直径)
1912: [Apio2010]patrol 巡逻 Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2).接下来 n – 1行,每行两个整数 a, b, 表示村庄a与b之间有一条道路(1 ≤ ...
随机推荐
- IT兄弟连 JavaWeb教程 Servlet会话跟踪 Cookie的优缺点
Cookie技术存储的数据类型只能是字符串,且不支持中文 ● 保存的数据大小有限,4kb ● 太依赖用户浏览器的设置,用户可以禁用Cookie! ● 数据存储在客户端的文本文件中,不安全,不建议 ...
- 阿里云物联网 .NET Core 客户端 | CZGL.AliIoTClient:4.1 上报位置信息
文档目录: 说明 1. 连接阿里云物联网 2. IoT 客户端 3. 订阅Topic与响应Topic 4. 设备上报属性 4.1 上报位置信息 5. 设置设备属性 6. 设备事件上报 7. 服务调用 ...
- UVA10140 Prime Distance【素数/数论】By cellur925
题目传送门 我们注意到,L,R是肥肠大的.........我们不可能在1s内筛出2^31内的全部质数. “上帝为你关上一扇门,同时为你打开一扇窗” 我们又注意到,R-L是肥肠比较小的,珂以从这入手解决 ...
- Linux 根据进程ID查看文件路径(转)
遇到的问题是想要查看进程的启动脚本在哪里,比如自己写的weblogic启动脚本,但忘记放在哪里了,这时候可以用以下方式 1.用ps -ef |grep xxxxx 得到该进程的pid 2.输入ls - ...
- nutz 使用beetl
src目录或src同级的其他目录(比如conf)下创建 beetl.properties文件,文件内容如下 (maven项目)在resources目录下创建 RESOURCE_LOADER=org.b ...
- DRF教程4-视图集和路由类
rest框架包括一个处理viewset的抽象,允许开发人员集中精力处理api交互和建模,url构造都根据常见方式自动处理. ViewSet类 几乎和VIew类一样,不过它提供read,update这样 ...
- python 基础(五) 迭代器与生成器
迭代器和生成器 迭代器 iterator (1) 迭代对象: 可以直接作用于for循环的 称为可迭代对象(iterable)可以通过 isinstance 判断是否属于可迭代对象 可以直接作用于for ...
- HDU1087(树状数组求LIS)
题是水题,学习一下用树状数组求LIS. 先离散化一下,注意去重:然后就把a[i]作为下标,dp[i]作为值,max作为维护的运算插进树状数组即可. 如果是上升子序列,询问(a[i] - 1):如果是不 ...
- 洛谷P2470||bzoj1068 [SCOI2007]压缩
bzoj1068 洛谷P2470 区间dp入门题?只要注意到每个M“管辖”的区间互不相交即可 错误记录:有点小坑,比如aaaacaaaac最优解为aRRcR(意会坑在哪里),踩了一次 #include ...
- linux 打开FTP 功能
http://blog.csdn.net/jay285979220/article/details/62216622 今天在linux上安装完了vsftpd后,使用root账号一直无法登陆到服务器上. ...