BZOJ1912或洛谷3629 [APIO2010]巡逻
一道树的直径
BZOJ原题链接
洛谷原题链接
显然在原图上路线的总长为\(2(n-1)\)。
添加第一条边时,显然会形成一个环,而这条环上的所有边全部只需要走一遍。所以为了使添加的边的贡献最大化,我们找出树的直径,将其两端点连上边即可。
设直径长\(L\),于是路线总长就变为\(2(n-1)-L+1=2n-L-1\)。
当\(K=1\)时,这就是答案。
当\(K=2\)时,我们考虑在上述添边后图中再添一条边。
添加这条边同样会形成一个环,如果这个环与之前的环没有边重合的话,那么贡献和上一边一样,但如果有重边,就会导致重边又需要走两边。
这就相当于添加的这条边在重边上的贡献为\(-1\),所以我们可以将第一次添边时搜到的直径上的所有边的权值改为\(-1\),然后依旧找出修改后的图的直径即可。
设第一条直径长\(L_1\),第二条长\(L_2\),那么最终路线总长就变为\(2(n-1)-L_1+1-L_2+1=2n-L_1-L_2\)。
另外,注意因为第二次找直径时,有边的权值为负,这时普通的\(dfs\)找直径是无法找到正确的直径的。
#include<cstdio>
using namespace std;
const int N = 1e5 + 10;
int di[N << 1], da[N << 1], ne[N << 1], fi[N], dis[N], D[N], dia, l;
inline int re()
{
int x = 0;
char c = getchar();
bool p = 0;
for (; c<'0' || c>'9'; c = getchar())
p |= c == '-';
for (; c >= '0'&&c <= '9'; c = getchar())
x = x * 10 + (c - '0');
return p ? -x : x;
}
inline void add(int x, int y)
{
di[++l] = y;
da[l] = 1;
ne[l] = fi[x];
fi[x] = l;
}
inline int maxn(int x, int y)
{
return x > y ? x : y;
}
void dfs(int x, int fa, int d)
{
int i, y;
if (dia < d)
{
dia = d;
D[0] = x;
}
D[x] = fa;
for (i = fi[x]; i; i = ne[i])
{
y = di[i];
if (y != fa)
dfs(y, x, d + 1);
}
}
void fixda(int x, int y)
{
int i;
for (i = fi[x]; i; i = ne[i])
if (di[i] == y)
{
da[i] = -1;
return;
}
}
void dp(int x, int fa)
{
int i, y;
for (i = fi[x]; i; i = ne[i])
{
y = di[i];
if (y != fa)
{
dp(y, x);
dis[0] = maxn(dis[0], dis[x] + dis[y] + da[i]);
dis[x] = maxn(dis[x], dis[y] + da[i]);
}
}
}
int main()
{
int i, n, m, x, y;
n = re();
m = re();
for (i = 1; i < n; i++)
{
x = re();
y = re();
add(x, y);
add(y, x);
}
dfs(1, 0, 0);
dia = 0;
dfs(D[0], 0, 0);
if (m == 1)
{
printf("%d", (n << 1) - dia - 1);
return 0;
}
for (x = D[0]; x; x = y)
{
y = D[x];
fixda(x, y);
fixda(y, x);
}
dp(1, 0);
printf("%d", (n << 1) - dia - dis[0]);
return 0;
}
BZOJ1912或洛谷3629 [APIO2010]巡逻的更多相关文章
- [洛谷P3629] [APIO2010]巡逻
洛谷题目链接:[APIO2010]巡逻 题目描述 在一个地区中有 n 个村庄,编号为 1, 2, ..., n.有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以 ...
- 洛谷 P3629 [APIO2010]巡逻 解题报告
P3629 [APIO2010]巡逻 题目描述 在一个地区中有 n 个村庄,编号为 1, 2, ..., n.有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以通 ...
- 洛谷 P3629 [APIO2010]巡逻
题目在这里 这是一个紫题,当然很难. 我们往简单的想,不建立新的道路时,从1号节点出发,把整棵树上的每条边遍历至少一次,再回到1号节点,会恰好经过每条边两次,路线总长度为$2(n-1)$,根据树的深度 ...
- 洛谷P3629 [APIO2010]巡逻(树的直径)
如果考虑不算上新修的道路,那么答案显然为\(2*(n-1)\). 考虑\(k=1\)的情况,会发现如果我们新修建一个道路,那么就会有一段路程少走一遍.这时选择连接树的直径的两个端点显然是最优的. 难就 ...
- [洛谷P3628] [APIO2010]特别行动队
洛谷题目链接:[APIO2010]特别行动队 题目描述 你有一支由 n 名预备役士兵组成的部队,士兵从 1 到 \(n\) 编号,要将他们拆分 成若干特别行动队调入战场.出于默契的考虑,同一支特别行动 ...
- 洛谷P3628 [APIO2010]特别行动队(动态规划,斜率优化,单调队列)
洛谷题目传送门 安利蒟蒻斜率优化总结 由于人是每次都是连续一段一段地选,所以考虑直接对\(x\)记前缀和,设现在的\(x_i=\)原来的\(\sum\limits_{j=1}^ix_i\). 设\(f ...
- Luogu 3629 [APIO2010]巡逻
先考虑$k = 1$的情况,很明显每一条边都要被走两遍,而连成一个环之后,环上的每一条边都只要走一遍即可,所以我们使这个环的长度尽可能大,那么一棵树中最长的路径就是树的直径. 设直径的长度为$L$,答 ...
- 洛谷P3628 [APIO2010]特别行动队(斜率优化)
传送门 先写出转移方程$$dp[i]=max\{dp[j]+a*(sum[i]-sum[j])^2+b*(sum[i]-sum[j])+c\}$$ 假设$j$比$k$更优,则有$$dp[j]+a*(s ...
- 洛谷P3628 [APIO2010]特别行动队 斜率优化
裸题,注意队列下标不要写错 Code: #include<cstdio> #include<algorithm> #include<cmath> using nam ...
随机推荐
- opencv输出图片像素值
需求:在控制台输出灰度图像的像素值 代码: #include <stdio.h> #include <iostream> #include <opencv2/core/c ...
- nbtscan工具
这是一款用于扫描Windows网络上NetBIOS名字信息的程序.该程序对给出范围内的每一个地址发送NetBIOS状态查询,并且以易读的表格列出接收到的信息,对于每个响应的主机,NBTScan列出它的 ...
- 第三章,DNA序列的进化演变
31.前言 3.1.两个序列间的核苷酸差异 来自同一祖先序列的两条后裔序列,之间的核苷酸的差异随着时间的增加而变大.简单的计量方法,p距离 3.2.核苷酸代替数的估计 3.3.Jukes和Cantor ...
- Flux architecture
[Flux architecture] Flux is a pattern for managing data flow in your application. The most important ...
- Excel学习之图表创建
前言:由于工作的需要,现在需要恶补Excel知识,温故而知新,不记录下来自己的学习的点点滴滴怎么能行 Excel版本:2016 一.插入如下图所示的数据源: 1.勾选图表区域范围 2.选中区域范围后直 ...
- 【scrapy】爬虫中报Forbidden by robots.txt
需要在setting.py里找到ROBOTSTXT_OBEY并设为false 来源:https://blog.csdn.net/yimingsilence/article/details/521197 ...
- Winform开发框架之简易工作流设计(转自 伍华聪博客)
Winform开发框架之简易工作流设计 一讲到工作流,很多人第一反应就是这个东西很深奥,有时候又觉得离我们较为遥远,确实完善的工作流设计很多方面,而正是由于需要兼顾很多方面,一般通用的工作流都难做到尽 ...
- openstack(Pike 版)集群部署(四)--- Nova 部署
一.介绍 参照官网部署:https://docs.openstack.org/nova/pike/install/ 继续上一博客进行部署:http://www.cnblogs.com/weiji ...
- fullCalendar插件基本使用
效果图 html代码,需要引入jquery,layui,fullCalendar <!DOCTYPE html> <html lang="en"> < ...
- javascript实现留言功能
原理: 1.用户在留言框输入留言 2.利用textarea的value属性获取到用户输入的留言 3.动态创建一个li 4.将获取的留言打包成html存到li中 5.根据需要添加删除留言.统计留言数量等 ...