Description
我们知道一棵有根树可以进行深度优先遍历(DFS)以及广度优先遍历(BFS)来生成这棵树的DFS序以及BFS序。两棵不同的树的DFS序有可能相同,并且它们的BFS序也有可能相同,例如下面两棵树的DFS序都是1 2 4 5 3,BFS序都是1 2 3 4 5
现给定一个DFS序和BFS序,我们想要知道,符合条件的有根树中,树的高度的平均值。即,假如共有K棵不同的有根树具有这组DFS序和BFS序,且他们的高度分别是h1,h2,...,hk,那么请你输出
(h1+h2..+hk)/k
Input
有3行。
第一行包含1个正整数n,表示树的节点个数。
第二行包含n个正整数,是一个1~n的排列,表示树的DFS序。
第三行包含n个正整数,是一个1~n的排列,表示树的BFS序。
输入保证至少存在一棵树符合给定的两个序列。
Output
仅包含1个实数,四舍五入保留恰好三位小数,表示树高的平均值。
Sample Input
5
1 2 4 5 3
1 2 3 4 5
Sample Output
HINT
【评分方式】
如果输出文件的答案与标准输出的差不超过0.001,则将获得该测试点上的分数,否则不得分。
【数据规模和约定】
20%的测试数据,满足:n≤10;
40%的测试数据,满足:n≤100;
85%的测试数据,满足:n≤2000;
100%的测试数据,满足:2≤n≤200000。
【说明】
树的高度:一棵有根树如果只包含一个根节点,那么它的高度为1。否则,它的高度为根节点的所有子树的高度的最大值加1。
对于树中任意的三个节点a , b , c ,如果a, b都是c的儿子,则a, b在BFS序中和DFS序中的相对前后位置是一致的,即要么a都在b的前方,要么a都在b的后方。
Source
这道题没有真的用到BFS和DFS,但需要对BFS和DFS有深刻的认识所以我就做不大出来这道题
首先根据我们对BFS序的理解,BFS序靠前的深度小于BFS序靠后的,所以我们根据BFS序就能划分出树有几层
*DFS序则能确定在同一深度的所有节点的左右顺序
但是这还不够,我们还要更多的条件来确定在什么时候是必须划分的
假设BFS序为1-n按序排列,在[1,2]处是必须分开的,设dfs序列为a[1...n],一个数i的DFS序下一位不为i+1,那么有两种可能:
(1)在i处换行了,而i这一行还有其他数,此时deep[i+1]+1=deep[i] (2)i没有儿子节点,所以向上回溯了
*所以不管怎样,如果i的DFS序下一位不为i+1,deep[i]+1>=deep[i+1]
带星号的两条可以用来判定一种方案的可行性,现在我们可以开始考虑怎么样去统计答案了
设X[i]表示在i和i+1处是否划分,1表示划分0表示不划分,根据上面规则
(1)X[1]=1
(2)if(pos[i]>pos[i+1]) X[i]=1
(3)if(a[i]<a[i+1]) X[a[i]]+X[a[i]+1]+...X[a[i+1]-1]<=1 (因为在dfs序上连续,a[i]和a[i+1]的深度只差最多为1,所以中间的节点最多分一次层)
通过(1)(2)我们能得出来一部分X=1,带入(3)能得出来一部分X=0
还有一些无法确定,既可能是1也可能是0,我们取个中间值0.5即可
处理的时候对每一段进行差分处理即可
代码:
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #define M 200010
5 using namespace std;
6 int n,top;
7 int t[M],a[M],st[M],pos[M],mark[M],s[M];
8 double ans,X[M];
9 int main()
10 {
11 scanf("%d",&n);
12 for(int i=1;i<=n;i++)
13 {
14 int k; scanf("%d",&k);
15 t[k]=i;
16 }
17 for(int i=1;i<=n;i++)
18 {
19 int k; scanf("%d",&k);
20 a[t[k]]=i;
21 pos[i]=t[k];
22 }
23 X[1]=1.0;
24 for(int i=1;i<n;i++)
25 {
26 if(pos[i]>pos[i+1]) X[i]=1.0;
27 if(X[i]==1.0)
28 {
29 mark[i]++;
30 mark[i+1]--;
31 }
32 s[i]=s[i-1]+X[i];
33 }
34 for(int i=1;i<n;i++)
35 if(a[i]<a[i+1])
36 {
37 if(s[a[i+1]-1]-s[a[i]-1]>0)
38 {
39 mark[a[i]]++;
40 mark[a[i+1]]--;
41 }
42 else st[++top]=a[i];
43 }
44 for(int i=1;i<=n;i++) mark[i]+=mark[i-1];
45 for(int i=1;i<=top;i++)
46 if(mark[st[i]]==0)
47 X[st[i]]=0.5;
48 for(int i=1;i<=n;i++) ans+=X[i];
49 printf("%.3lf",ans+1.0);
50 return 0;
51 }
来源:oschina
链接:https://my.oschina.net/u/4324524/blog/3847873