【树形DP】 珠宝(GEMS)

 珠宝(GEMS)

    给一棵n 个结点的树,给每个点安排一个正整数编号,使得相邻点具有不同的编号,编号的

总和尽量小。

输入文件:

  第一行:n(n<=50,000)

  以下n-1 行,每行两个数u,v(1<=u,v<=n),表示u和v 有一条边

输出文件:

  仅一行,为最小编号和

SAMPLE INPUT

8

1  2

1  3

1  4

1  5

5  6

5  7

5  8

SAMPLE OUTPUT

11
================

树形DP

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

type
  pnode=^node;
  node=record
         x:longint;
         next:pnode;
       end;
var
  n:longint;
  tree:array[1..50000]of pnode;
  //f_son:array[1..50000]of pnode;
  f_n,f_flag:array[1..50000,1..2]of longint;
  f:array[1..50000,1..50]of longint;
  f_bo:array[1..50000]of boolean;
procedure init;
begin
  assign(input,'gems.in');
  assign(output,'gems.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^.x:=b;
  p^.next:=tree[a];
  tree[a]:=p;
end;

procedure dfs(t:longint);
var
  p:pnode;
  i,j:longint;
  now:longint;
begin
  f_bo[t]:=false;
  p:=tree[t];
  while p<>nil do
    begin
      if f_bo[p^.x] then
        begin
          dfs(p^.x);
        end;
      p:=p^.next;
    end;
  for i:=1 to 50 do  //枚举根节点的分数..
    begin
      now:=0;
      p:=tree[t];
      while p<>nil do
        begin
          if f_flag[p^.x,1]<>0 then
            begin
              if f_flag[p^.x,1]=i then inc(now,f_n[p^.x,2])
                                  else inc(now,f_n[p^.x,1]);
            end;
          p:=p^.next;
        end;
      if now+i<f_n[t,1] then
        begin
          f_n[t,2]:=f_n[t,1]; f_flag[t,2]:=f_flag[t,1];
          f_n[t,1]:=now+i; f_flag[t,1]:=i;
          continue;
        end;
      if now+i<f_n[t,2] then
        begin
          f_n[t,2]:=now+i; f_flag[t,2]:=i;
        end;                              {更新}
    end;
end;

procedure main;
var
  i:longint;
  u,v:longint;
begin
  readln(n);
  for i:=1 to n do
    begin
      tree[i]:=nil;
    end;
  for i:=1 to n-1 do
    begin
      readln(u,v);
      insert(u,v);
      insert(v,u);
    end;
  fillchar(f_n,sizeof(f_n),$7);
  fillchar(f_flag,sizeof(f_flag),0);
  fillchar(f_bo,sizeof(f_bo),true);
  dfs(1);
  writeln(f_n[1,1]);
end;

begin
  init;
  main;
  terminate;
end.


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值