一道树的直径

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. SQL语句中LEFT JOIN、JOIN、INNER JOIN、RIGHT JOIN的区别?

    w3school的一套sql教程: http://www.w3school.com.cn/sql/index.asp left join :左连接,返回左表中所有的记录以及右表中连接字段相等的记录.r ...

  2. Linux系统下面crontab选择默认编译器

    crontab修改默认编辑器 crontab默认编辑器为nano. 修改crontab默认编辑器为vi或者其他的编辑器. 法一: export EDITOR="/usr/bin/vim&qu ...

  3. mongodb数据到MySQL数据库 的迁移步骤

    废话少说,直接上干货. 1.mongoexport -d shengyang -c testData -f _id,x,name,name1,name2 --type=csv -o new.csv 用 ...

  4. ssh架构之hibernate(四)二级缓存

    二级缓存使用步骤: 1.拷贝jar包 2.配置Hibernate.cfg.xml文件 a.#开启二级缓存 hibernate.cache.use_second_level_cache=true b.# ...

  5. 2.1、CDH 搭建Hadoop在安装(为Cloudera Manager配置存储库)

    步骤1:为Cloudera Manager配置存储库 使用包管理工具安装Cloudera Manager yum 对于RHEL兼容系统, zypper对于SLES,和 apt-get对于Ubuntu. ...

  6. js增减日期

    参考 https://www.cnblogs.com/gmq-sh/p/5194706.html date.setDate(date.getDate() + 3);

  7. 八:python 对象类型详解四:字典

    一:字典通识: 1,字典通过键而不是偏移量来读取: 2,字典是任意对象的无序集合: 3,字典可变长.异构.任意嵌套: 4,字典属于可变映射类型: 5,对象引用表(散列表): 二:实际应用中的字典: 1 ...

  8. 批量执行命令(SSH)

    for a in {1..6} ; do scp /etc/hosts enc-bigdata0$a:/etc/hosts ; done

  9. 20. Valid Parentheses (Stack)

    Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the inpu ...

  10. httpclient使用用例

    import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import jav ...