https://www.nowcoder.com/acm/contest/40/B
Time limit: 1 second for C / C + + and 2 seconds for other languages
Space limitation: C/C++ 131072K, other languages 262144 K
64bit IO Format: %lld
Title Description
Kodori gives you a rooted tree. Find out how many subtrees satisfy the internal node number to be continuous in the value field
The meaning that some numbers are continuous in the range means that they form a continuous range in the range
Enter a description:
The first row has an integer n that represents the number of nodes in the tree.
Next n – 1 lines, two integers x,y for each line, indicate that there is a directed edge from X to y.
The input guarantee is a rooted tree.
Output Description:
Output a number to indicate the answer
Example 1
input
5
2 3
2 1
2 4
4 5
output
5
Explain
No. 1 in the subtree of node 1, with continuous value field
Node 3 is numbered 3 in the subtree, and the value field is continuous
No. 5 in the subtree of node 5, with continuous value range
4,5 in the subtree of node 4, with continuous value range
No. 1,2,3,4,5 in the subtree of node 2, with continuous value range
remarks:
For 100% data, there are n < = 100000
Analysis: a subtree value range is continuous if and only if its subtree max min + 1 = size
dfs
1. Manual tree construction
#include <bits/stdc++.h>
using namespace std;
#define mem(a,n) memset(a,n,sizeof(a))
#define rep(i,a,n) for(int i=a;i<n;i++)
#define pb push_back
#define fi first
#define se second
typedef long long ll;
typedef unsigned long long ull;
const double eps=1e-6;
const int INF=0x3f3f3f3f;
const int N=1e5+5;
int ans,mx[N],mn[N],sz[N],cnt;
bool vis[N];
int head[N];
struct edge
{
int to,nxt;
}e[N];
void addedge(int u,int v)
{
cnt++;
e[cnt]=(edge){v,head[u]};
head[u]=cnt;
}
void dfs(int rt,int f)
{
mx[rt]=mn[rt]=rt;
sz[rt]=1;
for(int i=head[rt];i;i=e[i].nxt)
{
int nrt=e[i].to;
///if(nrt==f) continue; / / / to judge whether there is a ring or not, this problem is a directed tree, which is optional
dfs(nrt,rt);
mx[rt]=max(mx[rt],mx[nrt]);
mn[rt]=min(mn[rt],mn[nrt]);
sz[rt]+=sz[nrt];
}
if(mx[rt]-mn[rt]+1==sz[rt]) ans++;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
ans=cnt=0;
mem(vis,0);
int root;
rep(i,1,n)
{
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
vis[v]=1;
}
rep(i,1,n+1)
{
if(!vis[i])
{
root=i;
dfs(root,root);
break;
}
}
printf("%d\n",ans);
}
return 0;
}
2. Use vector
#include <bits/stdc++.h>
using namespace std;
#define mem(a,n) memset(a,n,sizeof(a))
#define rep(i,a,n) for(int i=a;i<n;i++)
#define pb push_back
#define fi first
#define se second
typedef long long ll;
typedef unsigned long long ull;
const double eps=1e-6;
const int INF=0x3f3f3f3f;
const int N=1e5+5;
int ans,mx[N],mn[N],sz[N];
bool vis[N];
vector<int>e[N];
void dfs(int rt)
{
mx[rt]=mn[rt]=rt;
sz[rt]=1;
rep(i,0,e[rt].size())
{
int next_rt=e[rt][i];
dfs(next_rt);
mx[rt]=max(mx[rt],mx[next_rt]);
mn[rt]=min(mn[rt],mn[next_rt]);
sz[rt]+=sz[next_rt];
}
if(mx[rt]-mn[rt]+1==sz[rt]) ans++;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
ans=0;
mem(vis,0);
rep(i,1,n)
{
int u,v;
scanf("%d%d",&u,&v);
vis[v]=1;
e[u].pb(v);
}
int root;
rep(i,1,n+1)
if(!vis[i])
{
root=i;
dfs(root);
break;
}
printf("%d\n",ans);
}
return 0;
}