Description
Input
Output
Sample Input
4
2 3
2 1
2 4
Sample Output
4
Data Constraint
Solution
首先,这是一棵有根树,先要找到它的根是哪个节点。
由于边是有向边,入度为零的点就是根节点了。
接着,如何处理出答案呢?
从根节点开始遍历这棵树,做一次 DFS。记录三个值:
- Size[i] 表示以 i 为根的子树的大小(节点数);
Mx[i] 表示以 i 为根的子树中节点标号最大是多少;Mn[i] 表示以 i 为根的子树中节点标号最小是多少;
那么对于一个节点
i ,如果满足:Mx[i]−Mn[i]+1=Size[i]则说明点 i 符合条件,答案加一。时间复杂度
O(N) 。
Code
#include<cstdio>
using namespace std;
const int N=100001;
int n,tot,ans;
int first[N],next[N],en[N];
int size[N],mx[N],mn[N];
bool bz[N];
inline int read()
{
int X=0,w=1; char ch=0;
while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
return X*w;
}
inline void dfs(int x)
{
size[mn[x]=mx[x]=x]=1;
for(int i=first[x];i;i=next[i])
{
dfs(en[i]);
size[x]+=size[en[i]];
if(mx[en[i]]>mx[x]) mx[x]=mx[en[i]];
if(mn[en[i]]<mn[x]) mn[x]=mn[en[i]];
}
if(mx[x]-mn[x]+1==size[x]) ans++;
}
int main()
{
int n=read();
for(int i=1;i<n;i++)
{
int x=read(),y=read();
next[++tot]=first[x];
first[x]=tot;
bz[en[tot]=y]=true;
}
for(int i=1;i<=n;i++)
if(!bz[i])
{
dfs(i);
break;
}
printf("%d",ans);
return 0;
}