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 ...
随机推荐
- Xshell 连接ubuntu虚拟机失败解决办法
当我们在VMWare上安装好Ubuntu虚拟机后,有时候会需要使用多个terminal窗口,但是在虚拟机中多个窗口互相切换查看不方便,这时候用物理机的xshell工具连接到虚拟机中去就显得很方便.直接 ...
- Json Web Token JJWT
什么是JWT? Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站 ...
- python -- 初始函数 函数的定义,函数的返回值以及函数的参数
1.什么是函数,函数的定义及语法 2.函数的返回值 3.函数的参数 一.函数的定义及语法 函数的定义:定义了一个动作或者功能,是对功能的封装 语法: def 函数名( 形参列表 ): ...
- mysql不能使用IP连接,可以使用localhost连接
问题: 本地mysql,使用127.0.0.1可以连接成功,使用具体IP连接报错 ERROR 1130 (HY000): Host '10.252.225.125' is not allowed to ...
- MySQL数据类型及使用场景
MySQL数据类型介绍 整数类型 类型名称 说明 存储需求 取值范围有符号 取值范围符号 TINYINT 很小的整数 1个字节 -128~127 0-255 SMALLINT 小的整数 2个字节 32 ...
- wamp 安装redis扩展
phpredis扩展下载地址 http://windows.php.net/downloads/pecl/snaps/redis/ 1.选择redis DLL文件扩展 phpinfo 查看VC版本 ...
- sqlserver自增主键
参考 https://www.cnblogs.com/michellexiaoqi/p/8031294.html 1.选中表: 2.右击鼠标,设计: 3.选中列(整数类 ...
- IronPython 的几个问题
1.在脚本中使用datagridview.Rows[i].Cells[1].Value并将其转换为string时,遇到int类型 有时可是直接使用.toString()转换为字符 有时必须采用str( ...
- Numpy函数库基础
利用Numpy函数库构造4*4随机数组,然后将数组转化为矩阵,然后矩阵与其逆矩阵相乘,计算机处理的误差 from numpy import * random.rand(4,4) print(rando ...
- centos 7 下 cobbler 安装
一.cobbler 介绍: Cobbler 是一个系统启动服务(boot server),可以通过网络启动(PXE)的方式用来快速安装.重装物理服务器和虚拟机,支持安装不同的 Linux 发行版和 W ...