【树形DP】爱心蜗牛

 

爱心蜗牛 

提交文件:badnews.pas/c/cpp

输入文件:badnews.in

输出文件:badnews.out 

猫猫把嘴伸进池子里,正准备“吸”鱼吃,却听到门铃响了。猫猫擦了擦脸上的水,打开门一看,那人正是她的好朋友——川川。

川川手里拿着一辆玩具汽车,对猫猫说:“这是我的新汽车!”接着,伴随一阵塑料叩击声,玩具汽车的车门竟开了,一只蜗牛慢慢吞吞爬了出来。

“哇!这么大的蜗牛……”猫猫惊讶道。

“这是我的宠物蜗牛,他叫点点。”川川介绍道。

“把他送给我好吗?”猫猫央求道。

“可以让他陪你几天,但是不能送给你……”

点点沿着川川的身体,爬到了地上,又移到了猫猫的池子旁边,只听见猫猫向川川介绍她的“创意吃鱼法”,心里不禁起了一丝凉意:“这个女生太毒了……吃鱼前还要玩鱼……”转眼一看,池中的鱼依旧畅快地游来游去。

“或许这些鱼听不懂猫语吧……好在我会一点儿猫语,也会一点鱼语……阿弥陀佛,善哉善哉。我还是救救这些鱼吧……”点点自言自语,一边费力地移动着身躯。他认识到——单凭自己的力量,把猫猫的阴谋告诉每一条鱼,似乎不太可能——自己底盘太低,走不快,看来只得想其他办法来传达信息。一翻认真思考之后,点点想到,如果把猫猫的计划告诉其中一条鱼,再让鱼们互相传达消息,那么在相对较短的时间内,每条鱼都会得知猫猫的计划。

鱼们的社会等级森严,除了国王菜鱼之外,每条鱼均有且只有一个直接上级,菜鱼则没有上级。如果A是B的上级,B是C的上级,那么A就是C的上级。

绝对不会出现这样两条鱼A、B:A是B的上级,B也是A的上级。

  最开始的时刻是0,点点要做的,就只是用1单位的时间把猫猫的阴谋告诉某一条“信息源鱼”,让鱼们自行散布消息。在任意一个时间单位中,任何一条已经接到通知的鱼,都可以把消息告诉他的一个直接上级或者直接下属。

现在,点点想知道:

1.到底需要多长时间,消息才能传遍池子里的鱼?

2.使消息传递过程消耗的时间最短,可供选择的“信息源鱼”有那些? 

输入数据:

第一行有一个数N(N≤1000),表示池中的鱼数,池鱼按照1到n编上了号码,国王菜鱼的标号是1。

第2行到第N行(共N-1行),每一行一个数,第I行的数表示鱼I的直接上级的标号。 

输出数据:

  对于每组输入数据:

  第一行有一个数,表示最后一条鱼接到通知的最早时间。

  第二行有若干个数,表示可供选择的鱼F的标号,按照标号从小到大的顺序输出,中间用空格分开。 

输入样例:

8

1

1

3

4

4

4

输出样例:

5

3 4 5 6 7

==========================

===================

type
  pnode=^node;
  node=record
         x:longint;
         next:pnode;
       end;
var
  n:longint;
  map:array[1..1000]of pnode;
  ans:longint;
  ansi:array[1..1000]of longint;
  f_bo:array[1..1000]of boolean;
  c:array[1..1000,1..1000]of longint;
  cs:array[1..1000]of longint;
  anss:longint;
procedure init;
begin
  assign(input,'badnews.in');
  assign(output,'badnews.out');
  reset(input); rewrite(output);
end;

procedure terminate;
begin
  close(input); close(output);
  halt;
end;

procedure insert(a,b:longint);
var
  p:pnode;
begin
  new(p);
  p^.next:=map[a];
  p^.x:=b;
  map[a]:=p;
end;

procedure qsort(s,t,n:longint);
var
  i,j:longint;
  tem:longint;
  x:longint;
begin
  i:=s; j:=t;
  x:=c[n,(s+t)shr 1];
  repeat
    while x<c[n,j] do dec(j);
    while c[n,i]<x do inc(i);
    if i<=j then
      begin
        tem:=c[n,j];
        c[n,j]:=c[n,i];
        c[n,i]:=tem;
        inc(i); dec(j);
      end;
  until i>j;
  if i<t then qsort(i,t,n);
  if s<j then qsort(s,j,n);
end;

function dfs(t:longint):longint;
var
  p:pnode;
  i:longint;
begin
  dfs:=0;
  f_bo[t]:=false; //标记当前点
  p:=map[t];
  cs[t]:=0;
  //表示t号节点有多少个元素..
  while p<>nil do
    begin
      if f_bo[p^.x] then
        begin
          inc(cs[t]);
          c[t,cs[t]]:=dfs(p^.x);
        end;
      p:=p^.next;
    end;
  if cs[t]=0 then exit(0);
  qsort(1,cs[t],t);
  for i:=1 to cs[t] do
    if dfs<c[t,i]+cs[t]+1-i then dfs:=c[t,i]+cs[t]+1-i;
  exit(dfs);
end;

procedure main;
var
  i:longint;
  x:longint;
  t:longint;
begin
  readln(n);
  for i:=1 to n do map[i]:=nil;
  for i:=2 to n do
    begin
      read(x);
      insert(i,x);
      insert(x,i);
    end;
  ans:=maxlongint;
  for i:=1 to n do
    begin
      fillchar(f_bo,sizeof(f_bo),true);
      t:=dfs(i);
      if t<ans then
        begin
          ans:=t;
          anss:=1;
          ansi[anss]:=i;
        end
        else
        if t=ans then
          begin
            inc(anss);
            ansi[anss]:=i;
          end;
    end;
  writeln(ans+1);
  for i:=1 to anss do write(ansi[i],' ');
end;

begin
  init;
  main;
  terminate;
end.


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值