给出一颗有根树,总共 n 个节点,如果一个节点的度不小于它所有的儿子以及他的父亲的度(如果存在父亲或者儿子),那么我们称这个点为 p 节点,现在给你一棵树你需要统计出 p 节点的个数。
这里的度数指树上的度数,即一个节点的子节点数。
输入格式
输入的第一行包含一个整数 t(1≤t≤100),表示数据组数。
接下来 t 组数据,每组数据第一行一个数 n(1≤n≤1000),表示树的节点数。
然后 n−1 行,每行两个数 x,y(0<x,y<n),代表 y 是 x 的儿子节点。
输出格式
输出 t 行,每一行一个整数,代表 p 节点的个数。
样例输入:
1 5 1 2 1 3 1 4 4 5
样例输出:
1
解题思路: 运用广度优先搜索对每个节点进行判断
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N=1e6+5;
int out[N],q[1005],n,m;
int e[N],ne[N],h[N],idx,father[N];
bool st[N];
void add(int a,int b)//建立邻接表
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int BFS()//运用广度搜索来判断每个节点是否符合条件
{
int sum=0,tt=0,hh=1;
memset(q,0,sizeof q);
for(int i=1;i<=n;i++)
if(!out[father[i]])//先将根节点入队
{
q[++tt]=i;//根节点入队
st[i]=true;//标记这个节点已经入过队了
}
while(tt>=hh)
{
int t=q[hh++],f=0;//f用于标记 t 这个节点是否符合条件
if(out[t]<out[father[t]])
{
f=1; //如果 t这个节点出度小于父节点的子出度则不符合题意
}
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(out[t]<out[j]) //如果 t 这个节点的出度于子节点的出度 则不符合题意
{
f=1;
}
if(!st[j])//如果该节点未搜索过则入队
{
st[j]=true;
q[++tt]=j;
}
}
if(!f) sum++;//符合题意则增加
}
return sum;
}
int main()
{
int t;cin>>t;
while(t--)
{
cin>>n;
memset(h,-1,sizeof h);
memset(st,false,sizeof st);
memset(out,0,sizeof out);
memset(father,0,sizeof father);
memset(e,0,sizeof e);
memset(ne,0,sizeof ne);
idx=0;
for(int i=1;i<n;i++)
{
int a,b;cin>>a>>b;
add(a,b);
out[a]++;//a的出度增加,也就是子节点个数
father[b]=a;//存储b的父节点
}
cout<<BFS()<<endl;
}
}