HDU3887(树dfs序列+树状数组)

Counting Offspring

Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2424 Accepted Submission(s): 838


Problem Description
You are given a tree, it’s root is p, and the node is numbered from 1 to n. Now define f(i) as the number of nodes whose number is less than i in all the succeeding nodes of node i. Now we need to calculate f(i) for any possible i.

Input
Multiple cases (no more than 10), for each case:
The first line contains two integers n (0<n<=10^5) and p, representing this tree has n nodes, its root is p.
Following n-1 lines, each line has two integers, representing an edge in this tree.
The input terminates with two zeros.

Output
For each test case, output n integer in one line representing f(1), f(2) … f(n), separated by a space.

Sample Input
15 7
7 10
7 1
7 9
7 3
7 4
10 14
14 2
14 13
9 11
9 6
6 5
6 8
3 15
3 12
0 0

Sample Output
0 0 0 0 0 1 6 0 3 1 0 0 0 2 0

思路: dfs序+树状数组。c++可调整栈的大小.#pragma comment(linker,"/STACK:1024000000,1024000000") 两个1024000000均为字节数。

#pragma comment(linker,"/STACK:1024000000,1024000000")
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN=100005;
struct Edge{
    int to,net;
}es[MAXN+MAXN];
int n,root;
int head[MAXN],tot;
int lch[MAXN],rch[MAXN],key;
int bit[MAXN];
int res[MAXN];
void addedge(int u,int v)
{
    es[tot].to=v;
    es[tot].net=head[u];
    head[u]=tot++;
}
void dfs(int u,int fa)
{
    lch[u]=++key;
    for(int i=head[u];i!=-1;i=es[i].net)
    {
        int v=es[i].to;
        if(v!=fa)    
        {
            dfs(v,u);
        }
    }
    rch[u]=key;
}
void add(int i,int x)
{
    while(i<MAXN)
    {
        bit[i]+=x;
        i+=(i&-i);
    }
}
int sum(int i)
{
    int s=0;
    while(i>0)
    {
        s+=bit[i];
        i-=(i&-i);
    }
    return s;
}
int main()
{
    while(scanf("%d%d",&n,&root)!=EOF&&(n+root)!=0)
    {
        memset(bit,0,sizeof(bit));
        memset(head,-1,sizeof(head));
        memset(res,0,sizeof(res));
        tot=0;
        key=0;
        for(int i=0;i<n-1;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            addedge(u,v);
            addedge(v,u);
        }
        dfs(root,-1);
        for(int i=1;i<=n;i++)
        {
            res[i]=sum(rch[i])-sum(lch[i]-1);
            add(lch[i],1);
        }
        for(int i=1;i<n;i++)
        {
            printf("%d ",res[i]);
        }
        printf("%d\n",res[n]);
    }
    return 0;
}

 第二版:

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int MAXN=100005;
vector<int> arc[MAXN];
int n,root;
int bit[MAXN];
void add(int i,int x)
{
    while(i<MAXN)
    {
        bit[i]+=x;
        i+=(i&(-i));
    }
}
int sum(int i)
{
    int s=0;
    while(i>0)
    {
        s+=bit[i];
        i-=(i&(-i));
    }
    return s;
}
int res[MAXN],vis[MAXN];
void dfs(int u)
{
    vis[u]=1;
    res[u]=sum(u);
    add(u,1);
    for(int i=0;i<arc[u].size();i++)
    {
        int to=arc[u][i];
        if(!vis[to])
        {
            dfs(to);
        }
    }
    res[u]=sum(u)-res[u]-1;
}
int main()
{
    while(scanf("%d%d",&n,&root)!=EOF&&(n||root))
    {
        memset(bit,0,sizeof(bit));
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++)    arc[i].clear();
        for(int i=0;i<n-1;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            arc[u].push_back(v);
            arc[v].push_back(u);
        }    
        dfs(root);
        for(int i=1;i<n;i++)
        {
            printf("%d ",res[i]);
        }
        printf("%d\n",res[n]);
    }
    return 0;
}

 

 

 

posted on 2016-07-21 20:10  vCoders  阅读(479)  评论(0编辑  收藏  举报

导航