珂朵莉的值域连续段

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld

题目描述

珂朵莉给你一个有根树,求有多少个子树满足其内部节点编号在值域上连续

一些数在值域上连续的意思即其在值域上构成一个连续的区间

输入描述:

第一行有一个整数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<map>
#include<queue>
#include<math.h>
#include<vector>
#include<string>
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#define inf 0x3f3f3f
#define ll long long
#define maxn 100005
using namespace std;
int vis[maxn];
int dis[maxn];
int a[maxn];
int mi[maxn],ma[maxn];
struct node
{
    int v;
    struct node *next;
}*h[maxn];
void LA(int u,int v)
{
    struct node *p=(struct node*)malloc(sizeof(struct node));
    p->v=v;
    p->next=h[u];
    h[u]=p;
}
void dfs(int x)
{
    a[x]=1;
    ma[x]=x;
    mi[x]=x;
    struct node *p;
    if(h[x]==NULL)
        return ;
    for(p=h[x]; p!=NULL; p=p->next)
    {
        int u=p->v;
        dfs(u);
        a[x]+=a[u];
        ma[x]=max(ma[x],ma[u]);
        mi[x]=min(mi[x],mi[u]);
    }
}
int main()
{
    int t;
    while(~scanf("%d",&t))
    {
int n=t;
        t--;

        int m=0;
        memset(vis,0,sizeof(vis));
        memset(ma,0,sizeof(ma));
        memset(mi,0,sizeof(mi));
        for(int i=0; i<maxn; i++)h[i]=NULL;
        while(t--)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            LA(x,y);
            vis[y]=1;
        }
        int ans=0;
        for(int i=1; i<=n; i++)
        {
            if(vis[i]==0)
            dfs(i);
        }
        for(int i=1; i<=n; i++)
        {
               if(a[i]==(ma[i]-mi[i]+1))
                    ans++;
        }
        cout<<ans<<endl;
    }
}








posted @ 2017-12-31 18:29  _大美  阅读(239)  评论(0编辑  收藏  举报