【题解】P3629 [APIO2010]巡逻
题意
有 \(n\) 个村庄,编号为 \(1, 2, ..., n\) 。有 \(n – 1\) 条道路连接着这些村 庄,从任何一个村庄都可以到达其他任一个村庄。道路长度均为 1。 巡警车每天要到所有的道路上巡逻。警察局设在编号为 \(1\) 的村庄里,每天巡警车总是从警察局出发又回到警察局。
在这些村庄之间建 \(K\) 条新的道路, 可以连接任意两个村庄。每天巡警车必须 经过新建的道路正好一次. 求最小的巡逻距离。
思路
非常有意思的一道题。顺便复习了直径的两种写法。
考虑逐条加边。
如果不加边,那么答案显然是 \(2(n-1)\).
如果加一条边,由于必须经过恰好一次,所以在沿着新的道路 \((u,v)\) 走了一次之后,要返回 \(u\) ,必须沿着树上的环的另一半再走一遍,那么这时候 \(u\to v\) 的路径只需要走一次,所以 \(ans=2(n-1)-L-+1.\)
再加一条边,如果环没有重叠,那么按照一条的情况处理即可。否则,重叠部分不会被走过,所以还要走一次,又变成了需要走两次的边。
总结两种情况,得到算法:
- 找一遍直径,边权取反,长度为 \(L_1\)
- 再求直径,得到 \(L_2\)
- \(ans=2(n-1)-(L_1-1)-(L_2-1)\)
代码
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct edge
{
int to,nxt,val;
}e[N<<1];
int n,k,tot=0,mx,head[N],dis[N],pre[N],f[N];
bool vis[N];
queue<int> q;
void add( int u,int v,int w )
{
e[++tot].to=v; e[tot].val=w; e[tot].nxt=head[u]; head[u]=tot;
}
int bfs( int s )
{
memset( dis,0x3f,sizeof(dis) );
q.push( s ); dis[s]=pre[s]=0;
while ( q.size() )
{
int t=q.front(); q.pop();
for ( int i=head[t]; i; i=e[i].nxt )
if ( dis[e[i].to]==0x3f3f3f3f )
dis[e[i].to]=dis[t]+e[i].val,pre[e[i].to]=i,q.push( e[i].to );
}
int res=1;
for ( int x=1; x<=n; x++ )
if ( dis[x]>dis[res] ) res=x;
return res;
}
void dp( int x )
{
vis[x]=1;
for ( int i=head[x]; i; i=e[i].nxt )
if ( !vis[e[i].to] )
{
dp( e[i].to );
mx=max( mx,f[e[i].to]+f[x]+e[i].val );
f[x]=max( f[x],f[e[i].to]+e[i].val );
}
}
int main()
{
memset( head,0,sizeof(head) ); tot=1;
scanf( "%d%d",&n,&k );
for ( int i=1,u,v; i<n; i++ )
scanf( "%d%d",&u,&v ),add( u,v,1 ),add( v,u,1 );
int l=bfs( 1 ); l=bfs(l);
int L1=dis[l],fl=1; mx=0;
if ( k==2 )
{
for ( ; pre[l]; l=e[pre[l]^1].to )
e[pre[l]].val=e[pre[l]^1].val=-1;
dp( 1 ); fl=2;
}
printf( "%d",2*(n-1)-L1-mx+fl );
return 0;
}
【题解】P3629 [APIO2010]巡逻的更多相关文章
- 洛谷 P3629 [APIO2010]巡逻 解题报告
P3629 [APIO2010]巡逻 题目描述 在一个地区中有 n 个村庄,编号为 1, 2, ..., n.有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以通 ...
- [洛谷P3629] [APIO2010]巡逻
洛谷题目链接:[APIO2010]巡逻 题目描述 在一个地区中有 n 个村庄,编号为 1, 2, ..., n.有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以 ...
- 题解 BZOJ 1912 && luogu P3629 [APIO2010]巡逻 (树的直径)
本来抄了篇题解,后来觉得题解都太不友好(我太菜了),一气之下自己打...一打打到第二天QAQ 首先什么边也不加时,总路程就是2*(n-1) 考虑k=1的时候,答案显然是2*(n-1)-直径+1=2*n ...
- P3629 [APIO2010]巡逻
题目描述 在一个地区中有 n 个村庄,编号为 1, 2, ..., n.有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以通过这些道路到达其 他任一个村庄.每条道 ...
- 洛谷 P3629 [APIO2010]巡逻
题目在这里 这是一个紫题,当然很难. 我们往简单的想,不建立新的道路时,从1号节点出发,把整棵树上的每条边遍历至少一次,再回到1号节点,会恰好经过每条边两次,路线总长度为$2(n-1)$,根据树的深度 ...
- 树的直径初探+Luogu P3629 [APIO2010]巡逻【树的直径】By cellur925
题目传送门 我们先来介绍一个概念:树的直径. 树的直径:树中最远的两个节点间的距离.(树的最长链)树的直径有两种方法,都是$O(N)$. 第一种:两遍bfs/dfs(这里写的是两遍bfs) 从任意一个 ...
- 洛谷P3629 [APIO2010]巡逻(树的直径)
如果考虑不算上新修的道路,那么答案显然为\(2*(n-1)\). 考虑\(k=1\)的情况,会发现如果我们新修建一个道路,那么就会有一段路程少走一遍.这时选择连接树的直径的两个端点显然是最优的. 难就 ...
- P3629 [APIO2010] 巡逻 (树的直径)
(这道题考察了求直径的两种方法......) 在原图中,每条边要经过两次,增加1条后,形成了一个环,那么环上的边只需要经过一次了(大量画图分析得),再增加一条又会形成一个环,如果这两个环有重叠,重叠部 ...
- [APIO2010]巡逻(树的直径)
[APIO2010]巡逻 题目描述 在一个地区中有 n 个村庄,编号为 1, 2, ..., n.有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以通过这些道路到 ...
随机推荐
- mon到底能坏几个
如果是在做ceph的配置,我们会经常遇到这几个问题 问:ceph需要配置几个mon 答:配置一个可以,但是坏了一个就不行了,需要配置只是三个mon,并且需要是奇数个 问:ceph的mon能跟osd放在 ...
- linux系统中重启网卡后网络不通(NetworkManager篇)
一.故障现象 RHEL7.6系统,使用nmcli绑定双网卡后,再使用以下命令重启network服务后主机网络异常,导致无法通过ssh远程登录系统. # systemctl restart networ ...
- matlab 数组操作作业
写出下列语句的计算结果及作用 1.A= [2 5 7 3 1 3 4 2]; 创建二维数组并赋值 2.[rows, cols] = size(A); 把A的尺寸赋值给数组,rows为行, ...
- HDU100题简要题解(2020~2029)
HDU2020 绝对值排序 题目链接 Problem Description 输入n(n<=100)个整数,按照绝对值从大到小排序后输出.题目保证对于每一个测试实例,所有的数的绝对值都不相等. ...
- centos8 安装lnmp
1. 最小化安装 2. 配置基本信息 hostnamectl set-hostname aaa_name 为了每次系统重新启动时,都可以获取更大的ulimit值,将ulimit 加入到/etc/pro ...
- vue springboot利用easypoi实现简单导出
vue springboot利用easypoi实现简单导出 前言 一.easypoi是什么? 二.使用步骤 1.传送门 2.前端vue 3.后端springboot 3.1编写实体类(我这里是dto, ...
- python基础之操作列表
遍历元素 magicians = ['alice','david','carolina'] for magician in magicians: print(magician) magicians = ...
- Oracle表空间和他的数据文件
//以myspace为例 来源于Oracle 11g数据库应用简明教程 清华出版社 /*创建表空间*/ CREATE TABLESPACE myspace DATAFILE'E:\develop\or ...
- C语言讲义——结构体struct
结构体是一种变量类型,可以包含多个变量(变量类型不必相同). 结构体的关键字是struct也是一种值类型. 例:设计一个表示"书本"的结构体: structBook { chari ...
- 如何让文科生5分钟写上Python
序言 这篇文章是转型后发表的第一篇文章,有必要先聊一下我的写文计划. 串行文章和并行文章 我会按照发文顺序分为串行文章和并行文章.Python 语言本身的内容,我会按照入门.进阶.原理的顺序依次展开. ...