[APIO2010]巡逻题解

[APIO2010]巡逻

在一个地区中有 n 个村庄,编号为 1, 2, …, n。有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以通过这些道路到达其 他任一个村庄。每条道路的长度均为 1 个单位。 为保证该地区的安全,巡警车每天要到所有的道路上巡逻。警察局设在编号 为 1 的村庄里,每天巡警车总是从警察局出发,最终又回到警察局。 下图表示一个有 8 个村庄的地区,其中村庄用圆表示(其中村庄 1 用黑色的 圆表示),道路是连接这些圆的线段。为了遍历所有的道路,巡警车需要走的距 离为 14 个单位,每条道路都需要经过两次。
为了减少总的巡逻距离,该地区准备在这些村庄之间建立 K 条新的道路, 每条新道路可以连接任意两个村庄。两条新道路可以在同一个村庄会合或结束 (见下面的图例(c))。 一条新道路甚至可以是一个环,即,其两端连接到同一 个村庄。 由于资金有限,K 只能是 1 或 2。同时,为了不浪费资金,每天巡警车必须 经过新建的道路正好一次。

这道题其实在紫题并不算难,最初考试时候遇到了这道题之后我太水,只有k==1的分数
首先来分析一下k=1的情况,当k=1时候,加一条边,省去的相当于两点原来的距离,所以,为了省去的尽可能多,我们考虑最长的路径(卖关子

最长的路径是什么???直径

所以,当k=1时,问题就简单了(虽然我当时打了很久),我们只需求出树的直径在直径,在其上建边。若直径长l,答案就是2(n-1)-l+12(n−1)−l+1。
于是k==1就这样轻松地解决了。
然后。。。由于不怎么会树的直径,就打了个dfs
特别丑的代码如下:

#include <bits/stdc++.h>
#define FOR(i,n,m) for(int i=n;i<=m;++i)
#define FR(i,n,m) for(int i=n;i>=m;--i)
const int N=100010;
int n,h[N<<1],cnt;
struct node {
   
	int next,to,w;
} e[N<<1];
#define add(u,v,w) e[++cnt]= (node){h[u],v,w};h[u]=cnt;
#define n(i) e[i].next
#define t(i) e[i].to
#define QXX(u) for(int i=h[u],v;v=t(i),i;i=n(i))
using namespace std;
int f[N],_max,k;

void dfs(int u,int fa,int w) {
   
	f[u]=w;
	QXX(u) if(v!=fa) dfs(v,u,w+e[i].w);
}

int main() {
   
	scanf("%d",&n);
	FOR(i,1,n-1) {
   
		int u,v,w;
		scanf("%d%d%d",&
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值