[BZOJ 1912] patrol 巡逻
Link:https://www.lydsy.com/JudgeOnline/problem.php?id=1912
Algorithm:
K=0:res=(n-1)*2 每条边恰好走2遍
K=1:res=res-树上最长链+1
由于每形成环,环上的边对答案的贡献都会-1,因此只要将树上最长链连成环即可
K=2:res=res-树上当前最长链+1
将原树上直径的边的边权赋为-1,表示如果原直径边同时出现在第2个环时对答案贡献增加1(变为2)
证明:第二次求最长链相当于对第一次的“反悔”操作,重复的边表示没有变化
相当于是把两条交错的最长链变成了两条分开的链,其和必然是不交错的两条链中最大的(否则可以用最长链代替)
Code:
#include <bits/stdc++.h> using namespace std; inline int read()
{
char ch;int num,f=;
while(!isdigit(ch=getchar())) f|=(ch=='-');
num=ch-'';
while(isdigit(ch=getchar())) num=num*+ch-'';
return f?-num:num;
} const int MAXN=1e5+;
int n,k,ch[MAXN][],mx[MAXN][],mx_node,dia,res=; struct edge
{
int to,nxt,val;
}G[MAXN*];
int head[MAXN],cnt=; void add_edge(int u,int v)
{
G[++cnt].to=v;G[cnt].nxt=head[u];head[u]=cnt;G[cnt].val=;
} void dfs(int u,int anc) //一遍dfs求树的直径
{
mx[u][]=mx[u][]=;
for(int i=head[u];i;i=G[i].nxt)
{
int v=G[i].to;
if(v==anc) continue;
dfs(v,u);
if(mx[u][]<mx[v][]+G[i].val)
{
mx[u][]=mx[u][],mx[u][]=mx[v][]+G[i].val;
ch[u][]=ch[u][],ch[u][]=i;
}
else if(mx[u][]<mx[v][]+G[i].val)
mx[u][]=mx[v][]+G[i].val,ch[u][]=i;
} if(mx[u][]+mx[u][]>dia)
dia=mx[u][]+mx[u][],mx_node=u;
} int main()
{
n=read();k=read();
for(int i=;i<n;i++)
{
int x=read(),y=read();
add_edge(x,y);add_edge(y,x);
} dfs(,);res=*(n-)-dia+;
if(k==) return cout << res,;
for(int i=ch[mx_node][];i;i=ch[G[i].to][]) G[i].val=G[i^].val=-;
for(int i=ch[mx_node][];i;i=ch[G[i].to][]) G[i].val=G[i^].val=-;
dia=;dfs(,);res=res-dia+; cout << res; return ;
}
Review:
1、树的直径的求法
以前只会双dfs法
其实可以一遍dfs,
使用记录最长子链和次长子链的方法,如果存在最长“父链”比次长子链大的情况,其会被包含在祖先的情况中
Resources:https://blog.csdn.net/ilsswfr/article/details/52078089
2、如果对无向边有修改操作,用链式前向星记录
因为正反向边的序号相邻,可以一起更新
3、求解高维度问题时(k个不相交链的最大长度和),
可以采取贪心求解每个子问题(当前最长链) + 构建反悔机制(走完后边权赋为-1)来解决问题
[BZOJ 1912] patrol 巡逻的更多相关文章
- 【BZOJ】【1912】【APIO2010】patrol巡逻
树形DP 说是树形DP,其实就是求树的最长链嘛…… K=1的时候明显是将树的最长链的两端连起来最优. 但是K=2的时候怎么搞? 考虑第一次找完树的最长链以后的影响:第一次找过的边如果第二次再走,对答案 ...
- BZOJ 1912:[Apio2010]patrol 巡逻(树直径)
1912: [Apio2010]patrol 巡逻 Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2).接下来 n – 1行,每行两个整数 a, b, 表示村庄a与b之间有一条道路(1 ≤ ...
- 【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 ...
- 【BZOJ1912】[Apio2010]patrol 巡逻 树形DP
[BZOJ1912][Apio2010]patrol 巡逻 Description Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2).接下来 n – 1行,每行两个整数 a, b, 表示 ...
- BZOJ 1912: [Apio2010]patrol 巡逻 (树的直径)(详解)
题目: https://www.lydsy.com/JudgeOnline/problem.php?id=1912 题解: 首先,显然当不加边的时候,遍历一棵树每条边都要经过两次.那么现在考虑k==1 ...
- bzoj 1912 : [Apio2010]patrol 巡逻 树的直径
题目链接 如果k==1, 显然就是直径. k==2的时候, 把直径的边权变为-1, 然后在求一次直径. 变为-1是因为如果在走一次这条边, 答案会增加1. 学到了新的求直径的方法... #includ ...
- 【BZOJ】1912: [Apio2010]patrol 巡逻(树的直径)
题目 传送门:QWQ 分析 $ k=1 $ 时显然就是树的直径 $ k=2 $ 时怎么做呢? 做法是把一开始树的直径上的边的边权改成$ -1 $,那么当我们第二次用这些边做环时就抵消了一开始的贡献. ...
- bzoj 1912: [Apio2010]patrol 巡逻【不是dp是枚举+堆】
我是智障系列.用了及其麻烦的方法= =其实树形sp就能解决 设直径长度+1为len(环长) 首先k=1,直接连直径两端就好,答案是2*n-len 然后对于k=2,正常人的做法是树形dp:先求直径,然后 ...
随机推荐
- json 串转成 java 对象再拼接成前台 html 元素
获取商品参数 json 串,转成 java 对象,再拼接成前台 html 的Service方法 @Override public String getItemParam(Long itemId) { ...
- Codeforces Round #523 (Div. 2) A. Coins
A. Coins 题目链接:https://codeforc.es/contest/1061/problem/A 题意: 给出n和s,要在1-n中选数(可重复),问最少选多少数可以使其和为s. 题解: ...
- 修改centos的源
最近都在使用国内的VPS.系统统一使用的都是Linux系统.但是,有一些服务商的系统给默认设置的是国外的.这样就会导致下载速度缓慢.于是,找到了国内几家比较热门的镜像点.奉献给大家.下面的镜像全部支持 ...
- 如何取消PPT中的动画效果
幻灯片放映——>设置放映式——>勾选放映时不加动画 (office2007)
- oracle有关游标的知识
一:前言 今天我自己第二次写游标,我擦,觉得自己在数据库方面需要很大的提高啊.今天遇到三个问题,第一个是oracle数据库中的数据拆分的问题,这个我用regexp_substr来进行解决,第二个问题就 ...
- 给 ecplise 配置struts2配置环境
下面介绍在Eclipse中配置Struts2的过程: 一.下载Struts2,因为Struts2是开源的,百度或者google一下就可以找到下载地址.我下载的是struts-2.3.1.2版本 的,解 ...
- 栈的图文解析 和 对应3种语言的实现(C/C++/Java)【转】
概要 本章会先对栈的原理进行介绍,然后分别通过C/C++/Java三种语言来演示栈的实现示例.注意:本文所说的栈是数据结构中的栈,而不是内存模型中栈.内容包括:1. 栈的介绍2. 栈的C实现3. 栈的 ...
- 【poj3415-Common Substrings】sam子串计数
题意: 给出两个串,问这两个串的所有的子串中(重复出现的,只要是位置不同就算两个子串),长度大于等于k的公共子串有多少个. 题解: 这题好像大神们都用后缀数组做..然而我在sam的题表上看到这题,做 ...
- codevs3304 水果姐逛水果街Ⅰ
题目描述 Description 水果姐今天心情不错,来到了水果街. 水果街有n家水果店,呈直线结构,编号为1~n,每家店能买水果也能卖水果,并且同一家店卖与买的价格一样. 学过oi的水果姐迅速发现了 ...
- C++异常~二 转
Linux 下 C++ 异常处理技巧 处理固有语言局限性的四种技术 处理 C++ 中的异常会在语言级别上遇到少许隐含限制,但在某些情况下,您可以绕过它们.学习各种利用异常的方法,您就可以生产更可靠的应 ...