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 巡逻的更多相关文章

  1. 【BZOJ】【1912】【APIO2010】patrol巡逻

    树形DP 说是树形DP,其实就是求树的最长链嘛…… K=1的时候明显是将树的最长链的两端连起来最优. 但是K=2的时候怎么搞? 考虑第一次找完树的最长链以后的影响:第一次找过的边如果第二次再走,对答案 ...

  2. BZOJ 1912:[Apio2010]patrol 巡逻(树直径)

    1912: [Apio2010]patrol 巡逻 Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2).接下来 n – 1行,每行两个整数 a, b, 表示村庄a与b之间有一条道路(1 ≤ ...

  3. 【BZOJ-1912】patrol巡逻 树的直径 + DFS(树形DP)

    1912: [Apio2010]patrol 巡逻 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 1034  Solved: 562[Submit][St ...

  4. [Apio2010]patrol 巡逻

    1912: [Apio2010]patrol 巡逻 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 2541  Solved: 1288[Submit][S ...

  5. 【BZOJ1912】[Apio2010]patrol 巡逻 树形DP

    [BZOJ1912][Apio2010]patrol 巡逻 Description Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2).接下来 n – 1行,每行两个整数 a, b, 表示 ...

  6. BZOJ 1912: [Apio2010]patrol 巡逻 (树的直径)(详解)

    题目: https://www.lydsy.com/JudgeOnline/problem.php?id=1912 题解: 首先,显然当不加边的时候,遍历一棵树每条边都要经过两次.那么现在考虑k==1 ...

  7. bzoj 1912 : [Apio2010]patrol 巡逻 树的直径

    题目链接 如果k==1, 显然就是直径. k==2的时候, 把直径的边权变为-1, 然后在求一次直径. 变为-1是因为如果在走一次这条边, 答案会增加1. 学到了新的求直径的方法... #includ ...

  8. 【BZOJ】1912: [Apio2010]patrol 巡逻(树的直径)

    题目 传送门:QWQ 分析 $ k=1 $ 时显然就是树的直径 $ k=2 $ 时怎么做呢? 做法是把一开始树的直径上的边的边权改成$ -1 $,那么当我们第二次用这些边做环时就抵消了一开始的贡献. ...

  9. bzoj 1912: [Apio2010]patrol 巡逻【不是dp是枚举+堆】

    我是智障系列.用了及其麻烦的方法= =其实树形sp就能解决 设直径长度+1为len(环长) 首先k=1,直接连直径两端就好,答案是2*n-len 然后对于k=2,正常人的做法是树形dp:先求直径,然后 ...

随机推荐

  1. transition(动画属性)

    CSS 过渡(transition)是通过定义元素从起点的状态和结束点的状态,在一定的时间区间内实现元素平滑地过渡或变化的一种补间动画机制.你可以让属性的改变过程持续一段时间,而不是立即生效. 通过t ...

  2. jaspersoft中分组打印

    一:前言 使用IReport已经四个月了,最近在做一个保镖,是要按照类型分类,并且这些类型要横着打印,最后还要算这个类型金额的总值,这张报表现是说需要用到子报表,最后和一个同事一起用group来分组做 ...

  3. 浏览器web端详解

    一.背景介绍浏览器是前端工程师或页面重构师工作中必不可少的,WEB页面运行在各种各样的浏览器当中,浏览器载入.渲染页面的速度直接影响着用户体验,特别是浏览器渲染页面的原理,页面渲染就是浏览器将HTML ...

  4. 【转】vs2015一键卸载干净

    插件是国外的一位同行写的,偶然在网上发现感觉挺好用,分享一下. 第二步.下载工具并解压 网盘下载地址:https://pan.baidu.com/s/1eSHRYxW 也可以在Github上下载最新版 ...

  5. JavaScript设置获取和设置属性的方法

    这篇文章主要介绍了JavaScript设置获取和设置属性的方法,学会使用getAttribute.setAttribute的用法,需要的朋友可以参考下   getAttribute 该方法用来获取元素 ...

  6. [Leetcode Week8]Edit Distance

    Edit Distance 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/edit-distance/description/ Description ...

  7. SQLAlchemy中filter()和filter_by()有什么区别

    from:https://segmentfault.com/q/1010000000140472 filter: apply the given filtering criterion to a co ...

  8. 记一次CUDA编程任务

    这个月6号开始,着手解决一个具有实际意义的计算任务.任务数据有9879896条,每条包含30个整数,任务是计算每两条数据之间的斯皮尔相关系数及其P值.原始数据只有500+MB,因此我并不认为这是个多么 ...

  9. servlet(6) - servlet总结 - 小易Java笔记

    垂阅前必看: 这都是我总结的我觉得是学习servlet应该掌握的,我在学习期间也做了一个博客项目来让所学的知识得以巩固.下面就是博客项目链接.前面的servlet相关的笔记总汇,还有就是我把觉得在学习 ...

  10. PhpExcel一些使用方法

    下面是总结的几个使用方法include 'PHPExcel.php';include 'PHPExcel/Writer/Excel2007.php';//或者include 'PHPExcel/Wri ...