链接:https://www.nowcoder.com/acm/contest/40/B
来源:牛客网
题目描述
珂朵莉给你一个有根树,求有多少个子树满足其内部节点编号在值域上连续
一些数在值域上连续的意思即其在值域上构成一个连续的区间
输入描述:
第一行有一个整数n,表示树的节点数。 接下来n–1行,每行两个整数x,y,表示存在一条从x到y的有向边。 输入保证是一棵有根树。
输出描述:
输出一个数表示答案
示例1
输入
5 2 3 2 1 2 4 4 5
输出
5
说明
节点1子树中编号为1,值域连续 节点3子树中编号为3,值域连续 节点5子树中编号为5,值域连续 节点4子树中编号为4,5,值域连续 节点2子树中编号为1,2,3,4,5,值域连续
备注:
对于100%的数据,有n <=100000
#include <bits/stdc++.h>
using namespace std;
const int mn = 100010;
int n;
queue<int>q[mn];
int mp[mn][3]; //0 区间最小值 1 区间最大值 2 节点数
bool vis[mn];
void dfs(int s)
{
int m=s,M=s,k=1;
while(!q[s].empty())
{
int t = q[s].front();
q[s].pop();
dfs(t);
//以t为根节点
m=min(m,mp[t][0]); //当前最小值+=子树节点数
M=max(M,mp[t][1]); //当前最大值+=子树节点数
k+=mp[t][2]; //当前节点数+=子树节点数
}
mp[s][0]=m;
mp[s][1]=M;
mp[s][2]=k;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
mp[i][0]=1e9;
mp[i][1]=-1;
}
for(int i=1;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
q[a].push(b);
vis[b]=1;
}
for(int i=1;i<=n;i++)
if(!vis[i])
dfs(i); //根节点
int ans=0;
for(int i=1;i<=n;i++)
{
if(mp[i][2]==mp[i][1]-mp[i][0]+1)
ans++;
}
printf("%d\n",ans);
return 0;
}