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

本文探讨了一种在树形结构中放置信标以确保每个节点可通过唯一距离序列识别的算法。通过深度优先搜索确定最少信标数量,并考虑了各种数据约束条件,适用于大型数据集。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值