题目在这里

这是一个紫题,当然很难。

我们往简单的想,不建立新的道路时,从1号节点出发,把整棵树上的每条边遍历至少一次,再回到1号节点,会恰好经过每条边两次,路线总长度为$2(n-1)$,根据树的深度优先遍历思想,很容易证明这个结论,因为每条边必然被递归一次,回溯一次。

建立1条新道路之后,因为新道路必须恰好经过一次(0次,2次都不可以),所以在沿着新道路(x,y)巡逻之后,要返回x,就必须沿着树上从y到x的路径巡逻一遍,最终形成一个环。与不建立新道路的情况相结合,相当于树上x与y之间的路径就只需经过一次了。

因此,当$k=1$时,我们找到树的最长链,在两个端点之间加一条新道路,就能让总的巡逻距离最小。若树的直径为L,答案就是$2(n-1)-L+1$。

建立第2条新道路(u,v)之后,又会形成一个环。若两条新道路形成的环不重叠,则树上u,v之间的路径只需经过一次,答案继续减小。否则,在两个环重叠的情况下,如果我们还按照刚才的方法把第2个环与建立1条新道路的情况相结合,两个环重叠的部分就不会被巡逻到。最终的结果是两个环重叠的部分由只需经过一次变回了需要经过两次。

综上所述,我们得到了如下算法:

1.在最初的树上求直径,设直径为$L1$。然后,把直径上的边权取反(从1改为-1)。

2.在最长链边权取反之后的树上再次求直径,设直径为$L2$。

答案就是$2(n-1)-(L1-1)-(L2-1)=2n-L1-L2$。如果L2这条直径包含L1取反的部分,就相当于两个环重叠。减掉$(L1-1)$后,重叠的部分变成了只需经过一次,减掉$(L2-1)$后,相当于把重叠的部分加回来,变回需要经过两次,与我们之前讨论相符。时间复杂度为$O(n)$。

code:

// luogu-judger-enable-o2
#include <bits/stdc++.h>
using namespace std; queue <int> q;
const int N=;
bool v[N];
int f[N];
int n,k,e=,cnt,p;
int s[N<<][],o[N],d[N],fa[N],w[N<<]; void add(int x,int y)
{
s[++e][]=y;s[e][]=o[x];o[x]=e;w[e]=;
} int bfs(int xx)
{
int ans=xx;
memset(v,,sizeof(v));
fa[xx]=;v[xx]=;d[xx]=;q.push(xx);
while (!q.empty()) {
int x=q.front();
for (int i=o[x];i;i=s[i][]) {
int y=s[i][];
if (!v[y]) {
fa[y]=x;d[y]=d[x]+;
if (d[y]>d[ans]) ans=y;
v[y]=;q.push(y);
}
}
q.pop();
}
return ans;
} void mark(int x)
{
int i=o[x];
while (i) {
int y=s[i][];
if (y!=fa[x]) {
if (v[x]&&v[y]) w[i]=w[i^]=-;
mark(y);
}
i=s[i][];
}
} void tree_dp(int x)
{
int mx=,i=o[x];
while (i) {
int y=s[i][];
if (y!=fa[x]) {
tree_dp(y);
p=max(p,mx+f[y]+w[i]);
mx=max(mx,f[y]+w[i]);
}
i=s[i][];
}
p=max(mx,p);f[x]=mx;
} int main()
{
int x,y;
cin>>n>>k;
for (int i=;i<n;i++) {
scanf("%d%d",&x,&y);
add(x,y);add(y,x);
}
int ss,t;
ss=bfs();t=bfs(ss);
bfs();
memset(v,,sizeof(v));
if (d[ss]<d[t]) swap(ss,t);
v[ss]=v[t]=;
while (d[ss]>d[t]) {
ss=fa[ss];v[ss]=;++cnt;
}
while (ss!=t) {
ss=fa[ss];t=fa[t];v[ss]=v[t]=;cnt+=;
}
if (k==) {cout<<(n-)*+-cnt<<endl;return ;}
if (cnt==n-) {cout<<n+<<endl;return ;}
mark();tree_dp();
cout<<(n-)*+-cnt-p<<endl;
return ;
}

洛谷 P3629 [APIO2010]巡逻的更多相关文章

  1. 洛谷 P3629 [APIO2010]巡逻 解题报告

    P3629 [APIO2010]巡逻 题目描述 在一个地区中有 n 个村庄,编号为 1, 2, ..., n.有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以通 ...

  2. [洛谷P3629] [APIO2010]巡逻

    洛谷题目链接:[APIO2010]巡逻 题目描述 在一个地区中有 n 个村庄,编号为 1, 2, ..., n.有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以 ...

  3. 洛谷P3629 [APIO2010]巡逻(树的直径)

    如果考虑不算上新修的道路,那么答案显然为\(2*(n-1)\). 考虑\(k=1\)的情况,会发现如果我们新修建一个道路,那么就会有一段路程少走一遍.这时选择连接树的直径的两个端点显然是最优的. 难就 ...

  4. BZOJ1912或洛谷3629 [APIO2010]巡逻

    一道树的直径 BZOJ原题链接 洛谷原题链接 显然在原图上路线的总长为\(2(n-1)\). 添加第一条边时,显然会形成一个环,而这条环上的所有边全部只需要走一遍.所以为了使添加的边的贡献最大化,我们 ...

  5. [洛谷P3628] [APIO2010]特别行动队

    洛谷题目链接:[APIO2010]特别行动队 题目描述 你有一支由 n 名预备役士兵组成的部队,士兵从 1 到 \(n\) 编号,要将他们拆分 成若干特别行动队调入战场.出于默契的考虑,同一支特别行动 ...

  6. 洛谷P3628 [APIO2010]特别行动队(动态规划,斜率优化,单调队列)

    洛谷题目传送门 安利蒟蒻斜率优化总结 由于人是每次都是连续一段一段地选,所以考虑直接对\(x\)记前缀和,设现在的\(x_i=\)原来的\(\sum\limits_{j=1}^ix_i\). 设\(f ...

  7. BZOJ1912 APIO2010 洛谷P3629 巡逻

    Description: 在一个地区中有 n 个村庄,编号为 1, 2, ..., n.有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以通过这些道路到达其 他任 ...

  8. 【洛谷 P3629】 [APIO2010]巡逻 (树的直径)

    题目链接 容易发现,当加一条边时,树上会形成一个环,这个环上的每个点都是只要走一次的,也就是说我们的答案减少了这个环上点的个数,要使答案最小,即要使环上的点最多,求出直径\(L\),则答案为\(2(n ...

  9. 洛谷 [P3629] 巡逻

    树的直径 树的直径有两种求法 1.两遍 dfs 法, 便于输出具体方案,但是无法处理负权边 2.DP 法,代码量少,可以处理负权边 #include <iostream> #include ...

随机推荐

  1. zabbix通过snmp监控windows主机

    1.开启Windows的snmp功能 2.配置snmp服务 设置snmp服务社区名称及允许的主机,设置完成后重启snmp服务 3.在zabbix server上测试 测试需要使用命令snmpwalk, ...

  2. 2017.10.13 git提交时忽略不必要的文件或文件夹

    参考来自:git学习六:git提交忽略不必要的文件或文件夹 1.应用场景 创建maven项目,使用git提交,有时需要忽略不必要的文件或文件夹,只保留一些基本. 例如如下截图,实际开发中我们只需提交: ...

  3. 2013年新统计全国省市县以及邮政编码SQL数据脚本

    USE [imei8com] GO /****** Object: Table [dbo].[Zone] Script Date: 03/12/2014 15:05:41 ******/ SET AN ...

  4. android:Cordova Android, hello Cordova ,PhoneGap android

    文章来自:http://blog.csdn.net/intbird 官方文档: http://cordova.apache.org/docs/en/5.0.0//index.html intbird的 ...

  5. Hadoop最大值的算法中出现的错误(strToDouble)

    错误信息: Exception in thread "main" java.lang.NumberFormatException: For input string: " ...

  6. react 打包后,项目部署完毕,刷新页面报错(404)

    原因解析: 之所以你在浏览器内可以由首页跳转到其他路由地址,是因为这是由前端自行渲染的,你在React Router定义了对应的路由,脚本并没有刷新网页访问后台,是JS动态更改了location. 当 ...

  7. 【HTML5】用脚本控制交互元素details元素的使用

    1.源码 <!. Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quo ...

  8. Hive命令行经常使用操作(数据库操作,表操作)

    数据库操作 查看全部的数据库 hive> show databases ; 使用数据库default hive> use default; 查看数据库信息 hive > descri ...

  9. Expression构建DataTable to Entity 映射委托 sqlserver 数据库里面金额类型为什么不建议用float,实例告诉你为什么不能。 sql server 多行数据合并成一列 C# 字符串大写转小写,小写转大写,数字保留,其他除外 从0开始用U盘制作启动盘装Windows10系统(联想R720笔记本)并永久激活方法 纯CSS打造淘宝导航菜单栏 C# Winform

    Expression构建DataTable to Entity 映射委托   1 namespace Echofool.Utility.Common { 2 using System; 3 using ...

  10. vim 标签页管理

    一.打开关闭标签页 1. :tabnew  新建标签页 2. :tabc     关闭当前标签页 3. :tabo     关闭其他标签页保留当前标签页 4. :tabe file  在新标签页中打开 ...