一道树的直径

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]巡逻的更多相关文章

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

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

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

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

  3. 洛谷 P3629 [APIO2010]巡逻

    题目在这里 这是一个紫题,当然很难. 我们往简单的想,不建立新的道路时,从1号节点出发,把整棵树上的每条边遍历至少一次,再回到1号节点,会恰好经过每条边两次,路线总长度为$2(n-1)$,根据树的深度 ...

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

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

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

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

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

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

  7. Luogu 3629 [APIO2010]巡逻

    先考虑$k = 1$的情况,很明显每一条边都要被走两遍,而连成一个环之后,环上的每一条边都只要走一遍即可,所以我们使这个环的长度尽可能大,那么一棵树中最长的路径就是树的直径. 设直径的长度为$L$,答 ...

  8. 洛谷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 ...

  9. 洛谷P3628 [APIO2010]特别行动队 斜率优化

    裸题,注意队列下标不要写错 Code: #include<cstdio> #include<algorithm> #include<cmath> using nam ...

随机推荐

  1. python import sklearn出错 "ImportError: DLL load failed: 找不到指定的模块。

    安装好sklearn模块后,import的时候出现了以下错误: 但是确实已经装好了,百思不得其解,网上查找之后发现,出现错误原因:安装包的来源问题,也可以理解为包版本兼容问题,有的包使用官方出版,有的 ...

  2. python列表中,多次追加元素

    在列表中追加元素,可以使用append(),列表相加也可以用extend()函数,多次追加元素可以用“+”实现 l=[1,2,3,4,5] x=6 y=7 z=8 l=l+[x]+[y]+[z] pr ...

  3. js高级-原型链

    JavaScript是基于原型的面向对象的语言(相当于一个基类,父类),而不是像Java通过类模板构造实例,通过原型实现属性函数的复用 函数都有 prototype属性 指向函数的原型对象 只有函数根 ...

  4. Ik分词器没有使用---------elasticsearch-analysis-ik 5.6.3分词问题

    此文章在作者认真阅读源码后发现,这并不是问题所在. 此篇文章是对IK配置的错误理解.新版本的IK配置的扩展字典本来就该使用者自己去手动配置! 1.问题 现在项目中用的是ES5.6.3的版本,在解决Fi ...

  5. 03_java基础(九)之综合练习与考核评估

    25.综合练习之车站业务分析 完成步骤: 需求: 以车站业务对车票做增删改查操作 1.建立数据库 2.建立车票表 3.建立java项目结构(model\dao\service\test) 4.创建mo ...

  6. python pbr 打包

    在之前学习stevedore时,在setup.py中使用setuptools打包发布了代码,然后调用代码中的实例化对象.参考我的文章 https://www.cnblogs.com/CaesarLin ...

  7. 学习笔记001之[Android开发视频教学].01_06_Android当中的常见控件

    文本框,按钮 菜单按钮(需复写两个方法) 后续需完成联系代码.

  8. 正则表达式pattern属性

    你发现自己多久匆匆编写一些正则表达式验证一个特定的文本. 多亏了新的pattern属性,我们可以在标签处直接插入一个正则表达式. <form action="" method ...

  9. 并查集和树的一些性质 hdu1325

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1325 题意是每次输入一对数字n,m表示一条树边,并且n是m的父亲,直到n==0&&m= ...

  10. javascript简单的选项卡

    实现一个简单的选项卡功能 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...