原题链接

题目描述

在一个地区有 n 个村庄,编号为1,2,…,n。

有 n-1 条道路连接着这些村庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以通过这些道路到达其他任一个村庄。

每条道路的长度均为1个单位。

为保证该地区的安全,巡警车每天都要到所有的道路上巡逻。

警察局设在编号为1的村庄里,每天巡警车总是从警局出发,最终又回到警局。

为了减少总的巡逻距离,该地区准备在这些村庄之间建立 K 条新的道路,每条新道路可以连接任意两个村庄。

两条新道路可以在同一个村庄会合或结束,甚至新道路可以是一个环。

因为资金有限,所以 K 只能为1或2。

同时,为了不浪费资金,每天巡警车必须经过新建的道路正好一次。

编写一个程序,在给定村庄间道路信息和需要新建的道路数的情况下,计算出最佳的新建道路的方案,使得总的巡逻距离最小。

输入格式

第一行包含两个整数 n 和 K。

接下来 n-1 行每行两个整数 a 和 b,表示村庄 a 和 b 之间有一条道路。

输出格式

输出一个整数,表示新建了 K 条道路后能达到的最小巡逻距离。

数据范围

\(3 \le n \le 100000\),
\(1 \le K \le 2\),
\(1 \le a,b \le n\)

输入样例:

8 1
1 2
3 1
3 4
5 3
7 5
8 5
5 6

输出样例:

11

解题报告

题意理解

有一颗\(n-1\)个节点的,警察局设在根节点,两个节点之间的距离固定\(1\),现在要求所有的节点都要至少访问一遍,可以访问多次.

猪八戒警察是个不愿意浪费多余时间的人死胖子,时间要花在睡觉吃饭上面,所以他只想要走最短的路.为什么胖,就是因为懒,贪吃

要致富先修路,于是上面派发了巨款修路,这笔巨款,居然可以添加一条路,或者两条路.巨款好多啊,全被猪八戒买东西吃掉了

不过有要求,那就是新修建的路,只准走一次,因为豆腐渣工程,不安全.


解题思路

题目分析

一道题目中,条件性质都是一座座宝藏,必须深入挖掘.才能成为yxc老师一般的人生赢家

  1. 题目的核心是什么?

偷懒走最少的路

  1. 换句话表示是什么?

不要走最长的路

  1. 什么是最长的路?

树的直径

  1. 树的直径是什么?

一棵树上,最远的两个点,他们的距离.

  1. 添加路径有什么效果?

使得两个点的最短距离变成\(1\).

  1. 当只能增加一条新的路径的时候,我们怎么最大化利润?

找到树的直径的两个端点,在他们中间添加一条新路径.

样例分析

[APIO2010] 算法竞赛竞赛经典 巡逻

这是我们样例1的模型.

让我们来求一下这棵树的树的直径

[APIO2010] 算法竞赛竞赛经典 巡逻

假如说我们将这条直径的两个端点连接的话,我们最多可以优惠多少路径长度呢?

[APIO2010] 算法竞赛竞赛经典 巡逻

性质是什么,就是从一个特殊例子,变化成为一个通解公式


性质总结

因此我们通过上面的每一步,得到了如下的这些重要性质.

  1. 刚开始我们一共要走的长度是:

\[路径总长度=2*(n-1)\\\\ n是这棵树上的节点个数 \]

因为对于每一个而言,我们必须要走两次. (你可以认为就像是DFS搜索一样)

第一次访问这个点,也就是进入这个点.

第二次访问这个点,也就是离开这个点.


  1. 假如说我们之前的树,它的树的直径长度\(L\),那么经过我们第一轮路径增加过后.

\[路径总长度-L+1 \\\\ 也就是2*(n-1)-L+1 \]

因为我们不必再走一遍树的直径了,所以我们减少了\(L\)的长度.

但是我们增加了一条边,所以我们增加了\(1\)的长度.

总而言之,言而总之,这就是我们对于增加一条边的性质总结.


重点思考

这道题目,不仅仅要让我们增加一条边,还有增加第二条边的可能.

假如说我们没有第一条边的建立,那么现在我们增加第二条边,其实所有步骤都是和上面建立第一条边是一样的.

  1. 第一条边建立后的影响

我们知道,树之所以是树,是因为它不会出现环.

但是现在一条边的建立,环它出现了.是他,是他,就是他,我们的小英雄一组环

因为出现了环,所以我们现在不能保证一个点,那就是

第二条边构造的B环会不会和第一条边构造的A环,有重叠部分.

  1. 假如说没有重叠部分

如果说没有重叠,那么第一条边和第二条边各自为政,井水不犯河水,我们可以看作是两次第一条边.

只需要把第一次步骤,重复两遍即可.

  1. 如果有重叠部分

我们现在要明确一点,为什么我们添加边,可以使得路径缩小?

因为对于树的直径上的所有点,我们只需要进入一次,并不需要再离开一次了.

  1. 但是重叠部分会导致什么呢?

对于一个节点而言,它是重叠部分上的点.

第一次,它被减少掉了一条边.

第二次,它再次被减少了一条边.

请问它还会被访问吗?

答案是不可能!因为我们一个节点,最多访问两次,而你减少了两次.

所以此时,我们的这些重叠部分上的点,从只需要访问一次,变成了需要访问两次.

因为我们必须去访问这些点,而访问了一次,又必须再离开一次,于是就是访问两次


算法流程
  1. 在最初的树上,求出树的直径\(L1\),然后将这条路径上的所有边权统统取反.

    \[1变成-1 \]

  2. 我们再求一次树的直径\(L2\).

  3. 答案就是

    \[2 \times (n-1)-(L1-1)-(L2-1) \\\\ = 2 \times (n-1)-L1+1-L2+1 \]

假如说\(L2\)\(L1\)有重叠部分.

那么当我们

\[-L1+1 \]

的时候,我们就会发现,重叠的部分变成了只需要经过一次.

然后

\[-L2+1 \]

相当于把重叠部分相加回来了.

此时变成了经过了两次.

假如说没有重叠部分,那么1,-1都不会有影响,反正我们不会经过这些边.


代码解析

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+20;
int n,k;
struct Edge
{
	int ver[2*N],edge[2*N],Next[2*N],head[N],dis[N],pre[N],f[N],v[N],tot,p,i,x,y,z;
	queue<int> q;
	void init()
	{
		memset(head,0,sizeof(head));
		tot=1;
	}
	void add_edge(int a,int b,int c)
	{
		edge[++tot]=b;
		ver[tot]=c;
		Next[tot]=head[a];
		head[a]=tot;
	}
	int bfs(int s)
	{
		int i,x,y;
		memset(dis,0x3f,sizeof(dis));
		q.push(s);
		dis[s]=pre[s]=0;
		while(q.size())
		{
			x=q.front();
			q.pop();
			for(i=head[x]; i; i=Next[i])
				if(dis[edge[i]]==0x3f3f3f3f)
					dis[edge[i]]=dis[x]+ver[i],pre[edge[i]]=i,q.push(edge[i]);
		}
		for(x=y=1; x<=n; x++)
			if(dis[x]>dis[y])
				y=x;
		return y;
	}
	int diam()
	{
		p=bfs(1);
		p=bfs(p);
		return dis[p];
	}
	void change()
	{
		for(; pre[p]; p=edge[pre[p]^1]) ver[pre[p]]=ver[pre[p]^1]=-1;
	}
	void dp(int x)
	{
		v[x]=1;
		for(int i=head[x]; i; i=Next[i])
			if(!v[edge[i]])
			{
				dp(edge[i]);
				y=max(y,f[edge[i]]+f[x]+ver[i]);
				f[x]=max(f[x],f[edge[i]]+ver[i]);
			}
	}
	void work()
	{
		x=diam(),y=0,z=1;
		if(k==2)
			change(),dp(1),z=2;
		printf("%d\n",2*(n-1)-x-y+z);
	}
} g1;
int main()
{
//	freopen("stdin.in","r",stdin);
	scanf("%d%d",&n,&k);
	g1.init();
	for(int i=1; i<n; i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		g1.add_edge(a,b,1);
		g1.add_edge(b,a,1);
	}
	g1.work();
	return 0;
}

相关文章:

  • 2022-02-08
  • 2021-10-26
  • 2021-11-03
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-12-04
  • 2021-05-30
  • 2022-12-23
  • 2022-02-16
  • 2021-09-30
  • 2021-05-28
  • 2021-07-14
相关资源
相似解决方案