[APC 001] -E Antennas on Tree

26 篇文章 0 订阅
22 篇文章 0 订阅
Atcoder传送门
洛谷传送门

题目翻译

有一棵 n n n个结点的树,边权均为 1 1 1
选择 k k k个结点 { x 1 , x 2 , . . . , x k } \{x_1,x_2, ..., x_k\} {x1,x2,...,xk}
每个结点 p p p可以表示为一个 k k k维向量 { d i s t ( p , x 1 ) , d i s t ( p , x 2 ) , . . . , d i s t ( p , x k ) } \{dist(p, x_1), dist(p, x_2), ..., dist(p, x_k)\} {dist(p,x1),dist(p,x2),...,dist(p,xk)}
最小化 k k k,使得每个 k k k维向量互不相同。
2 ≤ n ≤ 1 0 5 2 \le n \le 10^5 2n105

输入输出格式

输入格式

第一行一个正整数 n n n

以下 n − 1 n-1 n1行, 每行两个整数 a i , b i a_i,b_i ai,bi, 表示编号为 a i a_i ai b i b_i bi的节点之间有一条边。

输出格式

一行一个整数, 表示 k k k最小为多少。

输入输出样例

输入样例#1:
5
0 1
0 2
0 3
3 4
输出样例#1:
2
输入样例#2:
2
0 1
输出样例#2:
1
输入样例#3:
10
2 8
6 0
4 1
7 6
2 3
8 6
6 9
2 4
5 8
输出样例#3:
3
输入样例#4:
5
0 1
0 2
0 3
3 4
输出样例#4:
2
输入样例#5:
2
0 1
输出样例#5:
1
输入样例#6:
10
2 8
6 0
4 1
7 6
2 3
8 6
6 9
2 4
5 8
输出样例#6:
3

解题分析

可以发现, 如果两个点的距离为奇数, 那么显然是可以区分开的。

如果为偶数, 那么设这两个点为 a , b a,b a,b, 中点为 c c c, 显然必须要存在一个 x i x_i xi, 满足当以 c c c为根的时候, x i x_i xi a a a b b b在同一棵子树里。

换句话说, 以任何一个点作为根的时候,都至多有一棵子树内部没有 x i x_i xi

我们一遍 D F S DFS DFS就可以完成这个操作, 但要注意的是, 我们要考虑父节点方向是否有 x i x_i xi, 这就很麻烦了。

于是我们从一个度数 ≥ 3 \ge 3 3的节点开始 D F S DFS DFS, 也就保证了父节点方向一定有 x i x_i xi

代码如下:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cctype>
#include <vector>
#include <cstdlib>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MX 100500
template <class T>
IN void in(T &x)
{
	x = 0; R char c = gc;
	for (; !isdigit(c); c = gc);
	for (;  isdigit(c); c = gc)
	x = (x << 1) + (x << 3) + c - 48;
}
int n;
std::vector <int> nex[MX];
IN void add(R int from, R int to) {nex[to].push_back(from);}
int dp[MX];
void DFS(R int now, R int fa)
{
	bool fir = false;
	for (auto i : nex[now])
	{
		if (i == fa) continue;
		DFS(i, now);
		dp[now] += dp[i];
		if (!dp[i]) fir ? dp[now]++ : fir = true;
	}
}
int main(void)
{
	in(n); int foo, bar, rt = -1;
	for (R int i = 1; i < n; ++i)
	in(foo), in(bar), add(foo, bar), add(bar, foo);
	for (R int i = 0; i < n; ++i) if (nex[i].size() > 2) {rt = i; break;}
	if (~rt) DFS(rt, -1), printf("%d", dp[rt]);
	else puts("1"); 
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值