点击打开题目
Time Limit: 1 Sec Memory Limit: 128 MB Submit: 35 Solved: 10 Submit Status Web Board
985给你一棵“树”以及它的根节点,要求你先判定它是否是一棵树,其次他想知道每个节点的“太子”数目以及它的父亲(root的话输出自己)。
“太子判定条件”:
一、若x是y的孩子节点,那么x是y的“太子”;
二、若x是y的“太子”且y是z的“太子”,那么x是z的“太子”。
第一行输入一个整数t,代表有t组测试数据。
每组数据第一行输入两个整数n,root分别代表树的节点数目以及根节点的编号。
接下来n-1行,每行输出两个整数u,v代表u节点和v节点之间有一条树边。
注:1 <= t <= 20,1 <= n <= 1e4,1 <= root <= n,1 <= u,v <= n。
对每一组数据,若给定的“树”不合法输出NO即可,反之输出YES,接下来输出占两行:
第一行输出n个整数代表每个节点的“太子”数目,
第二行输出n个整数代表每个节点的父亲节点编号。
输出顺序从1到n,每两个数之间有一个空格,最后一个数后面没有空格。
2
3 1
1 2
2 3
2 1
1 1
YES
2 1 0
1 1 2
NO
hpu
首先并查集查询是否是一颗树(是否有重边,是否是“一颗”!)
然后在树上从root开始跑一遍bfs统计孩子数和父节点。
代码如下:
#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;
}