JZOJ-senior-5944. 【NOIP2018模拟11.01】信标

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/HuangXinyue1017/article/details/83821839

Time Limits: 1500 ms Memory Limits: 262144 KB

Description

在这里插入图片描述

Input

第一行一个正整数 n.
接下来 n − 1 行每行两个个正整数 u, v, 表示有一条连接 u, v 的道路.

Output

一行, 表示最少需要的信标数量.

Sample Input

4
1 2
1 3
1 4

Sample Output

2

样例 1 解释
在村庄 3, 4 放置信标, 四个村庄接收到的定位序列分别为 [1, 1], [2, 2], [0, 2], [2, 0].
如果只在 3 放置, 则村庄 2, 4 接收到的定位序列都是 [2], 不满足要求.
注意定位序列是有序的.

Data Constraint

样例 2
见下发文件中的 ex_beacon2.in/out.

Hint

对于前 20% 的数据, n ≤ 10;
对于前 45% 的数据, n ≤ 40, 树的形态随机;
对于前 70% 的数据, n ≤ 5000;
对于另 5% 的数据, 不存在一个村庄连接着 3 条或以上的道路;
对于 100% 的数据, 1 ≤ n ≤ 1000000, 1 ≤ u, v ≤ n, 保证数据合法.

Solution

题目大意:在一棵树上放标记,使得树上每个点能通过到标记的距离序列的不同被区分开
在这里插入图片描述

Code

#include<algorithm>
#include<cstdio>

#define fo(i,a,b) for(int i=a;i<=b;++i)

using namespace std;

const int N=1e6+5;
int n,num,f[N],d[N],last[N];
bool chain[N];
struct edge{int to,next;}e[2*N];

void link(int x,int y)
{
	e[++num]=(edge){y,last[x]},last[x]=num;
}

void dfs(int x,int fa)
{
	int son=0; bool bz=0;
	for(int w=last[x];w;w=e[w].next)
	{
		int y=e[w].to;
		if(y==fa) continue;
		++son,dfs(y,x);
		f[x]+=f[y];
		if(chain[y]) bz=1;
	}
	if(!son) f[x]=1,chain[x]=1;
	if(son==1&&bz) f[x]=1,chain[x]=1;
	if(son>1&&bz) f[x]--; 
}

int main()
{
	freopen("beacon.in","r",stdin);
	freopen("beacon.out","w",stdout);
	scanf("%d",&n);
	fo(i,1,n-1)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		link(x,y),link(y,x);
		++d[x],++d[y];
	}
	int rt=1;
	fo(i,1,n) if(d[i]>d[rt]) rt=i;
	if(!d[rt])
	{
		putchar('0');
		return 0;
	}
	if(d[rt]<=2)
	{
		putchar('1');
		return 0;
	}
	dfs(rt,0);
	printf("%d",f[rt]);
}

猜你喜欢

转载自blog.csdn.net/HuangXinyue1017/article/details/83821839