• pku3659 Cell Phone Network


    给定一棵树,要求对于每一个节点,要么自己放联络器,要么儿子放联络器,要么父亲放联络器,求让所有点满足条件的最少联络器数。

    一道经典的看守皇宫问题,用DP解决。

    f[0,now]表示在now节点放联络器的以now为根的子树的最小代价

    f[1,now]表示now节点不放联络器,被他的儿子联络的以now为根的子树的最小代价

    f[2,now]表示now节点不放联络器,被他的父亲联络的以now为根的子树的最小代价

    注意树的形态开始并不确定,需要DFS一次来建树。

    状态的转移在程序里很清楚,输出答案是min{f[0,1],f[1,1]}(我以1为根节点重建的树),因为根节点不可能再有父亲了,f[2,1]没有意义。

    View Code
      1 program pku3659(input,output);
    2 type
    3 node = ^link;
    4 link = record
    5 goal : longint;
    6 next : node;
    7 end;
    8 var
    9 l : array[0..10001] of node;
    10 v : array[0..10001] of boolean;
    11 tree : array[0..10001] of node;
    12 f : array[0..2,0..10001] of longint;
    13 n : longint;
    14 procedure add(xx,yy: longint );
    15 var
    16 tt : node;
    17 begin
    18 new(tt);
    19 tt^.goal:=yy;
    20 tt^.next:=l[xx];
    21 l[xx]:=tt;
    22 end; { add }
    23 procedure init;
    24 var
    25 i,x,y : longint;
    26 begin
    27 readln(n);
    28 for i:=1 to n do
    29 begin
    30 tree[i]:=nil;
    31 l[i]:=nil;
    32 end;
    33 for i:=1 to n-1 do
    34 begin
    35 readln(x,y);
    36 add(x,y);
    37 add(y,x);
    38 end;
    39 fillchar(f,sizeof(f),63);
    40 fillchar(v,sizeof(v),false);
    41 v[1]:=true;
    42 f[2,0]:=0;
    43 end; { init }
    44 procedure dfs(now : longint );
    45 var
    46 t,tt : node;
    47 begin
    48 t:=l[now];
    49 while t<>nil do
    50 begin
    51 if not v[t^.goal] then
    52 begin
    53 v[t^.goal]:=true;
    54 new(tt);
    55 tt^.goal:=t^.goal;
    56 tt^.next:=tree[now];
    57 tree[now]:=tt;
    58 dfs(t^.goal);
    59 end;
    60 t:=t^.next;
    61 end;
    62 end; { dfs }
    63 function min(aa,bb : longint ):longint;
    64 begin
    65 if aa<bb then
    66 exit(aa);
    67 exit(bb);
    68 end; { min }
    69 procedure dp(now : longint );
    70 var
    71 t : node;
    72 sum,minw : longint;
    73 flag : boolean;
    74 begin
    75 if now=0 then
    76 exit;
    77 if tree[now]=nil then
    78 begin
    79 f[0,now]:=1;
    80 f[1,now]:=maxlongint>>2;
    81 f[2,now]:=0;
    82 exit;
    83 end;
    84 t:=tree[now];
    85 while t<>nil do
    86 begin
    87 dp(t^.goal);
    88 t:=t^.next;
    89 end;
    90 sum:=0;
    91 t:=tree[now];
    92 while t<>nil do
    93 begin
    94 sum:=sum+min(f[0,t^.goal],min(f[1,t^.goal],f[2,t^.goal]));
    95 t:=t^.next;
    96 end;
    97 f[0,now]:=sum+1;
    98 sum:=0;
    99 t:=tree[now];
    100 while t<>nil do
    101 begin
    102 sum:=sum+min(f[0,t^.goal],f[1,t^.goal]);
    103 t:=t^.next;
    104 end;
    105 f[2,now]:=sum;
    106 flag:=false;
    107 sum:=0;
    108 t:=tree[now];
    109 while t<>nil do
    110 begin
    111 if f[1,t^.goal]>=f[0,t^.goal] then
    112 begin
    113 sum:=sum+f[0,t^.goal];
    114 flag:=true;
    115 end
    116 else
    117 sum:=sum+f[1,t^.goal];
    118 t:=t^.next;
    119 end;
    120 if flag then
    121 f[1,now]:=sum
    122 else
    123 begin
    124 minw:=maxlongint>>1;
    125 t:=tree[now];
    126 while t<>nil do
    127 begin
    128 if f[0,t^.goal]-f[1,t^.goal]<minw then
    129 minw:=f[0,t^.goal]-f[1,t^.goal];
    130 t:=t^.next;
    131 end;
    132 sum:=sum+minw;
    133 f[1,now]:=sum;
    134 end;
    135 end; { dp }
    136 procedure print;
    137 begin
    138 writeln(min(f[0,1],f[1,1]));
    139 end; { print }
    140 begin
    141 init;
    142 dfs(1);
    143 dp(1);
    144 print;
    145 end.



  • 相关阅读:
    学习进度条08
    学习进度条07
    子数组和最大值(二维)
    学习进度条06
    构建之法阅读笔记04
    四则运算网页版
    泛型代码中的默认关键字
    js 日期大小比较
    c#Reverse字符串
    c#获取数组中指定元素的索引
  • 原文地址:https://www.cnblogs.com/neverforget/p/2400576.html
Copyright © 2020-2023  润新知