首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【zzuliOJ】1900 - 985的“树”难题(bfs & 并查集)

【zzuliOJ】1900 - 985的“树”难题(bfs & 并查集)

作者头像
FishWang
发布2025-08-27 10:01:34
发布2025-08-27 10:01:34
13000
代码可运行
举报
运行总次数:0
代码可运行

点击打开题目

1900: 985的“树”难题

Time Limit: 1 Sec Memory Limit: 128 MB Submit: 35 Solved: 10 Submit Status Web Board

Description

985给你一棵“树”以及它的根节点,要求你先判定它是否是一棵树,其次他想知道每个节点的“太子”数目以及它的父亲(root的话输出自己)。

“太子判定条件”:

一、若x是y的孩子节点,那么x是y的“太子”;

二、若x是y的“太子”且y是z的“太子”,那么x是z的“太子”。

Input

第一行输入一个整数t,代表有t组测试数据。

每组数据第一行输入两个整数n,root分别代表树的节点数目以及根节点的编号。

接下来n-1行,每行输出两个整数u,v代表u节点和v节点之间有一条树边。

注:1 <= t <= 20,1 <= n <= 1e4,1 <= root <= n,1 <= u,v <= n。

Output

对每一组数据,若给定的“树”不合法输出NO即可,反之输出YES,接下来输出占两行:

第一行输出n个整数代表每个节点的“太子”数目,

第二行输出n个整数代表每个节点的父亲节点编号。

输出顺序从1到n,每两个数之间有一个空格,最后一个数后面没有空格。

Sample Input

2

3 1

1 2

2 3

2 1

1 1

Sample Output

YES

2 1 0

1 1 2

NO

HINT

Source

hpu

首先并查集查询是否是一颗树(是否有重边,是否是“一颗”!)

然后在树上从root开始跑一遍bfs统计孩子数和父节点。

代码如下:

代码语言:javascript
代码运行次数:0
运行
复制
#include <stdio.h>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
#define CLR(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
#define MAX 10000
int f[MAX+11];
int fa[MAX+11];
int ch[MAX+11];
bool flag;		//记录是否是树 
vector<int> edge[MAX+11];
void init(int n)
{
	flag = true;
	for (int i = 0 ; i <= n ; i++)
	{
		edge[i].clear();
		f[i] = i;
		ch[i] = 0;
		fa[i] = -1;
	}
}
int find(int x)
{
	if (x != f[x])
		f[x] = find (f[x]);
	return f[x];
}
bool join(int x,int y)
{
	int fx,fy;
	fx = find(x);
	fy = find(y);
	if (fx != fy)
	{
		f[fx] = fy;
		return true;
	}
	return false;
}
void bfs(int root,int father)
{
	if (edge[root].size() == 1 && edge[root][0] == father)		//如果只有父节点一条线,那么它是叶子
	{
		ch[root] = 0;
		return;		//递归终止 
	}
	for (int i = 0 ; i < edge[root].size() ; i++)		//否则搜索子节点 
	{
		int node = edge[root][i];
		if (node != father)
		{
			bfs(node,root);
			ch[root] += ch[node] + 1;		//加上子节点的孩子
			fa[node] = root;		//子节点的父亲是它 
		}
	}
}
int main()
{
	int u;
	int n,root;
	scanf ("%d",&u);
	while (u--)
	{
		scanf ("%d %d",&n,&root);
		init(n);
		for (int i = 1 ; i < n ; i++)
		{
			int t1,t2;
			scanf ("%d %d",&t1,&t2);
			edge[t1].push_back(t2);
			edge[t2].push_back(t1);
			if (!join(t1,t2))		//出现了环 
				flag = false;
		}
		if (!flag)
		{
			printf ("NO\n");
			continue;
		}
		int ant = 0;
		for (int i = 1 ; i <= n ; i++)
		{
			if (f[i] == i)
				ant++;
			if (ant > 1)
			{
				flag = false;
				break;
			}
		}
		if (!flag)
		{
			printf ("NO\n");
			continue;
		}
		//以上判断是否是树
		bfs(root,root);
		fa[root] = root;
		printf ("YES\n");
		for (int i = 1 ; i < n ; i++)
			printf ("%d ",ch[i]);
		printf ("%d\n",ch[n]);
		for (int i = 1 ; i < n ; i++)
			printf ("%d ",fa[i]);
		printf ("%d\n",fa[n]);
	}
	return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-08-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1900: 985的“树”难题
  • Description
  • Input
  • Output
  • Sample Input
  • Sample Output
  • HINT
  • Source
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档