链接: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; }