hdu 3887 Counting Offspring
生活随笔
收集整理的這篇文章主要介紹了
hdu 3887 Counting Offspring
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目連接:http://acm.hdu.edu.cn/showproblem.php?pid=3887
題意:給出一棵樹,對于每一個節點,問他的子孫節點中有多少個節點小于該節點。
思路:首先找出這棵樹的DFS序列,每一個節點出現在兩個位置,這兩個位置之間的節點就是該節點的子孫節點。
然后用樹狀數組求出這兩個位置之間有多少個節點小于該節點。
hdu這題出的有點齪 ,,用dfs搜索會爆棧,要手動模擬先序或者后序遍歷!
code:
View Code 1 # include<stdio.h>2 # include<string.h>
3 # define N 100050
4 struct node{
5 int from,to,next;
6 }edge[2*N],edge1[2*N];
7 int head[N],tol,head1[N],tol1,S[N],s[N],k,dp[N],count[N],visit[N],sig[N];
8 void add(int a,int b)
9 {
10 edge[tol].from=a;edge[tol].to=b;edge[tol].next=head[a];head[a]=tol++;
11 }
12 void add1(int a,int b)
13 {
14 edge1[tol1].from=a;edge1[tol1].to=b;edge1[tol1].next=head1[a];head1[a]=tol1++;
15 }
16 void dfs2(int root)
17 {
18 int j,top,u,v;
19 top=0;
20 k=0;
21 S[++top]=root;
22 while(top>0)
23 {
24 u=S[top];
25 if(!visit[u])
26 {
27 visit[u]=1;
28 s[++k]=u;
29 sig[u]=k;
30 }
31 for(j=head[u];j!=-1;j=edge[j].next)
32 {
33 v=edge[j].to;
34 if(visit[v]) continue;
35 S[++top]=v;
36 break;
37 }
38 if(j==-1)
39 {
40 top--;
41 dp[u]=k-sig[u];
42 }
43 }
44 }
45 void insert(int i)
46 {
47 while(i<=k)
48 {
49 count[i]++;
50 i+=i&(-i);
51 }
52 }
53 int query(int i)
54 {
55 int sum=0;
56 while(i>0)
57 {
58 sum+=count[i];
59 i-=i&(-i);
60 }
61 return sum;
62 }
63 int main()
64 {
65 int i,j,v,n,root,num[N],ans,node,a,b;
66 while(scanf("%d%d",&n,&root)!=EOF)
67 {
68 if(!n && !root) break;
69 tol=0;
70 memset(head,-1,sizeof(head));
71 for(i=1;i<n;i++)
72 {
73 scanf("%d%d",&a,&b);
74 add(a,b);
75 add(b,a);
76 }
77 memset(dp,0,sizeof(dp));
78 //dfs1(root,0);//樹形DP求節點子孫的個數
79 memset(visit,0,sizeof(visit));
80 dfs2(root);//模擬棧,先序遍歷
81 tol1=0;
82 memset(head1,-1,sizeof(head1));
83 for(i=1;i<=n;i++)
84 {
85 node=s[i];
86 ans=dp[node]+i;
87 add1(ans,node);
88 }
89 memset(count,0,sizeof(count));
90 for(i=1;i<=n;i++)
91 {
92 node=s[i];
93 num[node]=query(node-1);
94 insert(node);
95 for(j=head1[i];j!=-1;j=edge1[j].next)
96 {
97 v=edge1[j].to;
98 num[v]=query(v-1)-num[v];
99 }
100 }
101 printf("%d",num[1]);
102 for(i=2;i<=n;i++)
103 printf(" %d",num[i]);
104 printf("\n");
105 }
106 return 0;
107 }
轉載于:https://www.cnblogs.com/183zyz/archive/2011/09/30/2196452.html
總結
以上是生活随笔為你收集整理的hdu 3887 Counting Offspring的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据字典模版
- 下一篇: SI 9000 及阻抗匹配学习笔记(四)