题目:

  https://www.lydsy.com/JudgeOnline/problem.php?id=1912

题解:

  首先,显然当不加边的时候,遍历一棵树每条边都要经过两次。那么现在考虑k==1的情况,考虑加入的这一条边有什么作用。

显然,如图4边的作用就是使得原来的1-2-3-3-2-1路线变为了4-3-2-1或1-2-3-4,那么作用就是以多走一步的代价使得这条新边两端的两个结点的遍历路径长度减半。

  因此,想要使路径最短,就要使这条新边两端的两个结点之间的距离更长,显然,当两端的结点在原树中的路径为原树的直径时取得k==1时的最优解。设直径长度为dis,则k==1时ans=(n-1)*2-dis+1。

  那么,k==2的时候怎么办呢。显然直接求次长链的做法是错的,因为求次长链的时候会与直径的某些边重复,那么这些边就是没有意义的,答案显然不更优。

  因此,我们采用另一种方法:将直径上的边权全部置成-1,然后再跑一遍最长链。开始我也很不懂为什么要置成-1而不置成0,欸还是上面那张图是因为你考虑当你通过4边走到最下面那个点之后,显然你还是要回到最初的点的,而如果路径上的边与之前的直径重复,那么等于说你多加了一遍这条边,因此置成-1后不就相当于没加吗

  P.S.当边权有负数时求直径不能用两边dfs,而应该用dp。WA了好久qwq。。。于是我第一遍求直径时用的两边dfs,第二遍用的dp。。。

代码:

#include<bits/stdc++.h>

using namespace std;

const int maxn=;
int dep[maxn],fa[maxn],head[maxn],cnt=,root,ans,n,k,mdep[maxn],maxx; struct ed{
int next,to,w;
}e[maxn<<]; void add(int u,int v){
e[++cnt]=(ed){head[u],v,},head[u]=cnt;
e[++cnt]=(ed){head[v],u,},head[v]=cnt;
} void dfs(int now,int f){
fa[now]=f;mdep[now]=;
for(int i=head[now];i;i=e[i].next){
int tt=e[i].to;
if(tt==f) continue;
dep[tt]=dep[now]+e[i].w;
dfs(tt,now); mdep[now]=max(mdep[now],mdep[tt]+e[i].w);
}
} void dp(int now,int f){
int fm=-,sm=-;
for(int i=head[now];i;i=e[i].next){
int tt=e[i].to;
if(tt==f) continue;
if(mdep[tt]+e[i].w>sm){
if(mdep[tt]+e[i].w>fm)
swap(fm,sm),fm=mdep[tt]+e[i].w;
else
sm=mdep[tt]+e[i].w;
}
dp(tt,now);
}
maxx=max(maxx,fm+sm);
maxx=max(maxx,fm);
maxx=max(maxx,sm);
} int main(){
scanf("%d%d",&n,&k);
int u,v;
for(int i=;i<n;i++)
scanf("%d%d",&u,&v),add(u,v);
dfs(,);root=;
for(int i=;i<=n;i++)
if(dep[i]>dep[root])
root=i;
dep[root]=,dfs(root,);
for(int i=;i<=n;i++)
if(dep[i]>dep[root])
root=i;
ans=(n-)*-dep[root]+;
if(k==){
while(fa[root])
for(int i=head[root];i;i=e[i].next){
int tt=e[i].to;
if(tt==fa[root]){
e[i].w=e[i^].w=-;
root=fa[root];break;
}
}
dep[]=;maxx=-0x3f3f3f3f;
dfs(,);dp(,);
ans-=maxx-;
}
printf("%d",ans);
return ;
}

BZOJ 1912: [Apio2010]patrol 巡逻 (树的直径)(详解)的更多相关文章

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

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

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

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

  3. bzoj 1912: [Apio2010]patrol 巡逻

    呵呵呵呵呵呵,自己画图,大概半个小时,觉的连上边会成环(是不是该交仙人掌了??)然后求环不重合部分最大就好了, 结果写了一坨DP,最后写不下去了,再次扒了题解. 发现我真的是个sb. k==1,直接是 ...

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

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

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

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

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

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

  7. [Apio2010]patrol 巡逻

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

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

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

  9. AVL树平衡旋转详解

    AVL树平衡旋转详解 概述 AVL树又叫做平衡二叉树.前言部分我也有说到,AVL树的前提是二叉排序树(BST或叫做二叉查找树).由于在生成BST树的过程中可能会出现线型树结构,比如插入的顺序是:1, ...

随机推荐

  1. laravel中migration 数据迁移

    简介 数据库迁移就像是数据库的版本控制,可以让你的团队轻松修改并共享应用程序的数据库结构.迁移通常与 Laravel 的数据库结构生成器配合使用,让你轻松地构建数据库结构.如果你曾经试过让同事手动在数 ...

  2. centos 6.5 查看时区和设置时区

    centos6.x 和centos7.x在时区方面有点差距,本文是针对centos6.x进行介绍. 其实在我的一个博文里,在安装系统的时候就可以进行时区的设置,本文介绍的是用命令进行时区查看和设置. ...

  3. Python 爬虫 解析库的使用 --- Beautiful Soup

    知道了正则表达式的相关用法,但是一旦正则表达式写的有问题,得到的可能就不是我们想要的结果了.而且对于一个网页来说,都有一定的特殊结构和层级关系,而且有很多节点都有id或class来做区分,所以借助它们 ...

  4. 运维常用mysql语句

    1..select @@version; ##查询当前mysql的版本. 2. show variables like 'port';##查看mysql实例的端口. 3.show variables ...

  5. jedis集群版应用

    1.pom文件添加依赖: 2.创建配置文件 <!-- jedis集群版配置(JedisCluster通过构造传参(2个参数)) --> <bean id="redisCli ...

  6. Real-time chart using ASP.NET Core and WebSocket

    Solution in glance The following diagram illustrates our solution where IoT device reports readings ...

  7. default配置页面一级菜单用于进入二级菜单

  8. [IOI2018]机械娃娃——线段树+构造

    题目链接: IOI2018doll 题目大意:有一个起点和$m$个触发器,给出一个长度为$n$的序列$a$,要求从起点出发按$a$的顺序经过触发器并回到起点(一个触发器可能被经过多次也可能不被经过), ...

  9. Yahoo Programming Contest 2019 自闭记

    A:签到. #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> ...

  10. Codeforces551 C. GukiZ hates Boxes

    二分答案 + 贪心 传送门:$>here<$ $Solution$ 二分时间+贪心验证.思维难度主要在验证上,然而坑人的点却在n的取值上.那么先来谈如何验证.在已知时间的条件下,能否用一种 ...