Codevs P1814 最长链

21 篇文章 0 订阅
6 篇文章 0 订阅

Codevs P1814 最长链


题目描述 Description

现给出一棵N个结点二叉树,问这棵二叉树中最长链的长度为多少,保证了1号结点为二叉树的根。


输入输出 Input&Output


输入描述 Input Description


输入的第1行为包含了一个正整数N,为这棵二叉树的结点数,结点标号由1至N。
接下来N行,这N行中的第i行包含两个正整数l[i], r[i],表示了结点i的左儿子与右儿子编号。如果l[i]为0,表示结点i没有左儿子,同样地,如果r[i]为0则表示没有右儿子。


输出描述 Output Description

输出包括1个正整数,为这棵二叉树的最长链长度。

样例 Sample


样例输入 Sample Input

5
2 3
4 5
0 6
0 0
0 0


样例输出 Sample Output

4


数据范围及提示 Data Size & Hint

【样例说明】

4-2-1-3-6为这棵二叉树中的一条最长链。


【数据规模】

对于10%的数据,有N≤10;
对于40%的数据,有N≤100;
对于50%的数据,有N≤1000;
对于60%的数据,有N≤10000;
对于100%的数据,有N≤100000,且保证了树的深度不超过32768。

【提示】

关于二叉树:
二叉树的递归定义:二叉树要么为空,要么由根结点,左子树,右子树组成。左子树和右子树分别是一棵二叉树。
请注意,有根树和二叉树的三个主要差别:
1. 树的结点个数至少为1,而二叉树的结点个数可以为0;
2. 树中结点的最大度数没有限制,而二叉树结点的最大度数为2;
3. 树的结点无左、右之分,而二叉树的结点有左、右之分。
关于最长链:
最长链为这棵二叉树中一条最长的简单路径,即不经过重复结点的一条路径。可以容易证明,二叉树中最长链的起始、结束结点均为叶子结点。

分析

该题是求最长链,首先,由于边权均为1,所以可以采用2遍BFS的方法来求得,首先从任意一个点进行BFS,找出距其最远的一个点,然后再从最远的点进行一次BFS,此时找出的距离即为最远距离,这是建立在正边权的基础上进行的,如果有负边权,则该方法会有错误,正解应为树形DP,通过计算该点向下的深度加上向上的长度来求的最长链的长度。
该过程是先求得向下的深度,因为要知道该点的深度,必须先求的它的子节点的深度,所以可以先逐层深入到叶子节点,先求的下面的节点深度,再返回求得该点向下的深度。向上的长度是指通过其父节点走到长度,不一定必须向根那个方向走,而是可以通过根再向下走。
那么求得向上的长度必须应用到向下的深度,所以必须先进行计算向下的深度,再计算向上的长度,因为计算一个点向上的长度需要用到父亲的长度,所以要自上而下的计算,计算完该值后在深入到下层计算。


代码如下


DP求法

program p1814;
type point=^rec;
     rec=record
      e,v:longint;
      s:point;
     end;
var n,i,j,s,e,ans,temp:longint;
    up:array[1..1000] of longint;
    down:array[1..1000,1..2] of longint;
    vertex:array[1..10000] of point;
function max(a,b:longint):longint;
begin
 if a>b then exit(a);
 exit(b);
end;
procedure insert(s,e:longint);
var p:point;
begin
 new(p);
 p^.e:=e;
 p^.s:=vertex[s];
 vertex[s]:=p;
end;

procedure down_x(i:longint);
var p:point;
begin
 p:=vertex[i];
 while p<>nil do
  begin
   down_x(p^.e);
   if down[p^.e,1]+1>down[i,1]
    then
     begin
      down[i,2]:=down[i,1];
      down[i,1]:=down[p^.e,1]+1;
     end
    else
     begin
      if down[p^.e,1]+1>down[i,2]
       then
        begin
         down[i,2]:=down[p^.e,1]+1;
        end;
     end;
   p:=p^.s;
  end;
end;

procedure up_x(i:longint);
var p:point;
begin
 p:=vertex[i];
 while p<>nil do
  begin
   up[p^.e]:=up[i]+1;
   if down[i,1]=down[p^.e,1]+1
    then temp:=down[i,2]+1
    else temp:=down[i,1]+1;
   if temp>up[p^.e]
    then up[p^.e]:=temp;
   up_x(p^.e);
   p:=p^.s;
  end;
end;

begin
 readln(n);
 for i:=1 to n do
  begin
   readln(s,e);
   if s<>0 then
    insert(i,s);
   if e<>0 then
    insert(i,e);
  end;
 down_x(1);
 up[1]:=0;
 up_x(1);
 ans:=-maxlongint;
 for i:=1 to n do
  begin
   ans:=max(ans,down[i,1]+up[i]);
  end;
 write(ans);
end.

测试结果

运行结果
测试点#chain0.in 结果:AC 内存使用量: 128kB 时间使用量: 1ms
测试点#chain1.in 结果:AC 内存使用量: 128kB 时间使用量: 1ms
测试点#chain2.in 结果:AC 内存使用量: 128kB 时间使用量: 1ms
测试点#chain3.in 结果:AC 内存使用量: 128kB 时间使用量: 1ms
测试点#chain4.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
测试点#chain5.in 结果:AC 内存使用量: 624kB 时间使用量: 0ms
测试点#chain6.in 结果:AC 内存使用量: 1520kB 时间使用量: 12ms
测试点#chain7.in 结果:AC 内存使用量: 4464kB 时间使用量: 23ms
测试点#chain8.in 结果:AC 内存使用量: 4204kB 时间使用量: 42ms
测试点#chain9.in 结果:AC 内存使用量: 5872kB 时间使用量: 52ms



BFS求法

program line;
type point=^rec;
     rec=record
      e,v:longint;
      s:point;
     end;
     rec2=record
      s,v:longint;
     end;
var n,maxn,maxj,i,j,s,e,v:longint;
    queue:array[1..1000000] of rec2;
    visited:array[1..1000000] of boolean;
    vertex:array[1..100000] of point;
function max(a,b:longint):longint;
begin
 if a>b then exit(a);
 exit(b);
end;
procedure insert(s,e,v:longint);
var p:point;
begin
 new(p);
 p^.e:=e;
 p^.v:=v;
 p^.s:=vertex[s];
 vertex[s]:=p;
end;
procedure bfs(st:longint);
var head,rear:longint;
    p:point;
begin
 head:=1;
 rear:=1;
 queue[head].s:=st;
 queue[head].v:=0;
 visited[st]:=true;
 while head<=rear do
  begin
   p:=vertex[queue[head].s];
   while p<>nil do
    begin
     if not visited[p^.e]
      then
       begin
        inc(rear);
        queue[rear].s:=p^.e;
        queue[rear].v:=queue[head].v+p^.v;
        visited[p^.e]:=true;
        if maxn<queue[rear].v
         then
          begin
           maxn:=queue[rear].v;
           maxj:=p^.e;
          end;
       end;
     p:=p^.s;
    end;
   inc(head);
  end;
end;

begin
 readln(n);
 for i:=1 to n do
  begin
   readln(s,e);
   if s<>0 then
    begin
     insert(i,s,1);
     insert(s,i,1);
    end;
   if e<>0 then
    begin
     insert(i,e,1);
     insert(e,i,1);
    end;
   visited[i]:=false;
  end;
 maxn:=-maxlongint;
 bfs(1);
 for i:=1 to n do visited[i]:=false;
 bfs(maxj);
 if maxn<0 then write(0)
           else write(maxn);
end.

测试结果

运行结果
测试点#chain0.in 结果:AC 内存使用量: 128kB 时间使用量: 1ms
测试点#chain1.in 结果:AC 内存使用量: 128kB 时间使用量: 1ms
测试点#chain2.in 结果:AC 内存使用量: 128kB 时间使用量: 1ms
测试点#chain3.in 结果:AC 内存使用量: 128kB 时间使用量: 1ms
测试点#chain4.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
测试点#chain5.in 结果:AC 内存使用量: 624kB 时间使用量: 0ms
测试点#chain6.in 结果:AC 内存使用量: 1520kB 时间使用量: 12ms
测试点#chain7.in 结果:AC 内存使用量: 4464kB 时间使用量: 23ms
测试点#chain8.in 结果:AC 内存使用量: 4204kB 时间使用量: 42ms
测试点#chain9.in 结果:AC 内存使用量: 5872kB 时间使用量: 52ms


Forever&always

Once upon a time
回到那个夜晚
I believe it was a Tuesday When I caught your eye
我确定那时在星期二的晚上,我们目光相遇
We caught onto something
某些事将要发生在我们身上
I hold onto the night
相信那个晚上
you looked me in the eye and told me you loved me
你看着我,说了你爱我
Were you just kidding?
这不是在骗我吧?
Cause it seems to me,This thing is breaking down
因为这一切现在对我而言早已面目全非了
we almost never speak.I don’t feel welcome anymore
形同陌路的我们让我感觉被抛弃了
Baby what happened, Please tell me
亲爱的,请告诉我,到底发生了什么
Cause one second it was perfect
原本还是那么完美的一切
Now you’re halfway out the door
下一秒你已转身离去
And I stare at the phone, he still hasn’t called
我紧握着电话,但它没有如愿响起
And then you feel so low, you can’t feel nothing at all
这一切让人心灰意冷
And you flashback to when he said, forever and always
你承诺的永远还回响在我的耳边
Oh, and it rains in your bedroom, everything is wrong
噢,我躲在卧室哭泣,一切都变了
It rains when you’re here and it rains when you’re gone.
你离开了,雨却依旧下着
Cause I was there when you said forever and always.
我还停留在你向我承诺时的时光
Was I out of line? Did I say something way too honest
是我做错了什么?还是我说话太过直接?
Did you run and hide like a scared little boy
竟让你像个哭闹的小孩只会躲起来
I looked into your eyes.
看着你的眼睛
Though I knew you for a minute,Now I’m not so sure
原本熟悉的你竟变得如此陌生
So here’s to everything, coming down to nothing
原本美好的一切都不复存在
Here’s to silence that cuts me to the core
你的沉默不语彻底伤害了我
Where is this going?
以后会怎样
Thought I knew for a minute,but I don’t anymore
我真的不知道
And I stare at the phone, he still hasn’t called
我紧攥着电话,它仍然没有响起
And then you feel so low, you can’t feel nothing at all
这真让人心灰意冷
And you flashback to when he said, forever and always
你承诺的永远还回响在我的耳边
Oh, and it rains in your bedroom, everything is wrong
噢,我的天空下起大雨,我的世界不再美好。
It rains when you’re here and it rains when you’re gone.
你离开了,雨却依旧下着
Cause I was there when you said forever and always.
我还停留在你向我承诺时的时光
Did you mean it baby? I don’t think so
现在我终于明白你的承诺只是说说而已
Back up, baby back up
回来吧,宝贝回来吧
Did you forget everything?
你忘记了你做过的一切吗?
Back off, baby back off
后退,宝贝,后退
Did you forget everything?
你忘记了你做过的一切吗?
Cause it rains in your bedroom,, everything is wrong
哦,我的天空下起大雨,我的世界不再美好
It rains when you’re here and it rains when you’re gone
你离开了,雨却依旧下着
Cause I was there when you said forever and always
我还停留在你向我承诺时的时光
And I stare, at the phone
我紧盯着电话
He still hasn’t called
他依然没有打来
And then you feel so low you can’t feel nothing at all
这真让人心灰意冷
And you flashback to when we said
你承诺的永远还回响在我的耳边
Forever and always
永远,永远
And it rains in your bedroom, everything is wrong
我的天空下起大雨,我的世界不再美好。
It rains when you’re here and it rains when you’re gone
你离开了,雨却依旧下着
Cause I was there when you said
当我在这里的时候你说Forever and always
永远,永远
He didn’t mean it baby
他只是说说而已
You said forever and always
你说的永远永远


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值