【NOI2007】 追捕盗贼

题目描述
追捕盗贼
问题描述
魔法国度 Magic Land 里最近出现了一个大盗 Frank,他在 Magic Land 四处作
案,专门窃取政府机关的机密文件(因而有人怀疑 Frank 是敌国派来的间谍)
。
为了捉住 Frank,Magic Land 的安全局重拳出击!
Magic Land 由 N 个城市组成,并且这 N 个城市又由恰好 N-1 条公路彼此连
接起来,使得任意两个城市间都可以通过若干条公路互达。从数据结构的角度我
们也可以说,这 N 个城市和 N-1 条公路形成了一棵树。
例如,下图就是 Magic Land 的一个可能格局(4 个城市用数字编号,3 条公
路用字母编号)

大盗 Frank 能够在公路上以任意速度移动。
比方说,对于上图给出的格局,在 0.00001 秒钟内(或者任意短的一段时间
内)
,Frank 就可以从城市 1 经过城市 2 到达城市 4,中间经过了两条公路。
想要生擒 Frank 困难重重,所以安全局派出了经验丰富的警探,这些警探具
有非凡的追捕才能:
1. 只要有警探和 Frank 同处一个城市,那么就能够立刻察觉到Frank,并且将其逮捕。
2. 虽然 Frank 可以在公路上以任意快的速度移动,但是如果有警探和 Frank 在同一条公路上相遇,那么警探也可以立刻察觉到 Frank 并将其逮捕。
安全局完全不知道 Frank 躲在哪个城市,或者正在哪条公路上移动,所以需
要制定一个周密的抓捕计划,计划由若干步骤组成。在每一步中,可以做如下几
件事中的一个:
1. 在某个城市空降一位警探。警探可以直接从指挥部空降到 Magic
Land 的任意一个城市里。此操作记为“L x”,表示在编号为 x 的城市里空降一位警探。耗时 1 秒。
2. 把留在某个城市里的一位警探直接召回指挥部。以备在以后的步骤中再度空降到某个城市里。此操作记为“B x”。表示把编号为 x 的城市里的一位警探召回指挥部。耗时 1 秒。
3. 让待在城市 x 的一位警探沿着公路移动到城市 y,此操作记为“M x y”。耗时 1 秒。当然,前提是城市 x 和城市 y 之间有公路。如果在警探移动的过程中,大盗 Frank 也在同一条公路上,那么警探就抓捕到了Frank。
现在,由你来制定一套追捕计划,也就是给出若干个步骤,需要保证:无论大盗 Frank 一开始躲在哪儿,也无论 Frank 在整个过程中如何狡猾地移动(Frank大盗可能会窃取到追捕行动的计划书,所以他一定会想尽办法逃避),他一定会被缉拿归案。
希望参与的警探越少越好,因为经验丰富的警探毕竟不多。
例如对于前面所给的那个图示格局,一个可行的计划如下:
1. L 2 在城市 2 空降一位警探。注意这一步完成之后,城市 2 里
不会有 Frank,否则他将被捉住。
2. L 2 再在城市 2 空降一位警探。
3. M 2 1 让城市 2 的一位警探移动到城市 1。注意城市 2 里还留
有另一位警探。这一步完成之后,城市 1 里不会有 Frank,公路 A 上也
不会有 Frank。也就是说,假如 Frank 还没有被逮捕,那么他只能是在城
市 3 或城市 4 里,或者公路 B 或公路 C 上。
4. B 1 召回城市 1 的一位警探。注意虽然召回了这位警探,但是
由于我们始终留了一位警探在城市 2 把守,所以 Frank 仍然不可能跑到
城市 1 或者是公路 A 上。
5. L 3 在城市 3 空降一位警探。注意这一步可以空降在此之前被
召回的那位警探。这一步完成之后,城市 3 里不会有 Frank,否则他会被
捉住。
6. M 3 2 让城市 3 里的一位警探移动到城市 2。这一步完成之后,
如果 Frank 还没有被捉住,那他只能是在公路 C 上或者城市 4 里。注意
这一步之后,城市 2 里有两位警探。
7. M 2 4 让城市 2 里的一位警探移动到城市 4。这一步完成之后,
Frank 一定会被捉住,除非他根本就没来 Magic Land。
这个计划总共需要 2 位警探的参与。可以证明:如果自始至终只有 1 名或者
更少的警探参与,则 Frank 就会逍遥法外。
你的任务很简单:对于一个输入的 Magic Land 的格局,计算 S,也就是为了
追捕 Frank 至少需要投入多少位警探,并且给出相应的追捕计划步骤。
输入文件
输入文件给出了 Magic Land 的格局。
第一行一个整数 N,代表有 N 个城市,城市的编号是 1~N。
接下来 N-1 行,每行有两个用空格分开的整数 xi,yi,代表城市 xi,yi 之间
有公路相连。保证 1≤xi,yi≤N
输出文件
向输出文件输出你所给出的追捕计划。
第一行请输出一个整数 S,代表追捕计划需要多少位警探。
第二行请输出一个整数 T,代表追捕计划总共有多少步。
接下来请输出 T 行,依次描述了追捕计划的每一步。每行必须是以下三种形
式之一:
“L x”
,其中 L 是大写字母,接着是一个空格,再接着是整
数 x,代表在城市 x 空降一位警探。你必须保证 1≤x≤N。
“B x”
,其中 B 是大写字母,接着是一个空格,再接着是整
数 x,代表召回城市 x 的一位警探。你必须保证 1≤x≤N,且你的计
划执行到这一步之前,城市 x 里面确实至少有一位警探。
“M x y”
,其中 M 是大写字母,接着是一个空格,再接着是
整数 x,再跟一个空格,最后一个是整数 y。代表让城市 x 的一位警
探沿着公路移动到城市 y。你必须保证 1≤x, y≤N,且你的计划执行
到这一步之前,城市 x 里面确实至少有一位警探,且城市 x, y 之前
确实有公路。
必须保证输出的 S 确实等于追捕计划中所需要的警探数目。
样例输入
4
12
32
24
样例输出
2
7
L2
L2
M21
B1
L3
M32
M24
评分标准
对于任何一个测试点:
如果输出的追捕计划不合法,或者整个追捕计划的步骤数 T 超过了 20000,
或者追捕计划结束之后,不能保证捉住 Frank,则不能得分。
否则,用你输出的 S 和我们已知的标准答案 S*相比较:
1. 若 S<S*,则得到 120%的分。
2. 若 S=S*,则得到 100%的分。
3. 若 S*<S≤S*+2,则得到 60%的分。
4. 若 S*+2<S≤S*+4,则得到 40%的分。
5. 若 S*+4<S≤S*+8,则得到 20%的分。
6. 若 S>S +8,则得到 10%的分。
数据规模和约定
输入保证描述了一棵连通的 N 结点树,1≤N≤1 000

 

题解

 

解法1:树形DP
  1 (*
  2     Problem:    NOI2007 追捕盗贼
  3     Author :    Chen Yang
  4     Time   :    2012.5.30 3:12 pm
  5     State  :    96分
  6     Memo   :    树形DP
  7 *)
  8 program catch;
  9 type
 10   ty1=^ty2;
 11   ty2=record
 12     x:longint;
 13     next:ty1;
 14   end;
 15 var
 16   n,i,x,y,tot,min:longint;
 17   first:array[0..1010] of ty1;
 18   f,ms,g,tms:array[0..1010] of longint;
 19   s,t:array[0..1000010] of longint;
 20   op:array[0..1000010] of char;
 21 //==========================
 22 procedure insert(x,y:longint);
 23 var
 24   p:ty1;
 25 begin
 26   new(p); p^.x:=y;
 27   p^.next:=first[x]; first[x]:=p;
 28 end;
 29 //==========================
 30 procedure find(x,fa:longint);
 31 var
 32   p:ty1;
 33   max,t:longint;
 34 begin
 35   p:=first[x];  max:=0; t:=0;
 36   while p<>nil do
 37   begin
 38     if p^.x<>fa then
 39     begin
 40       find(p^.x,x);
 41       if max<g[p^.x] then begin max:=g[p^.x]; tms[x]:=p^.x; t:=0; end else
 42       if max=g[p^.x] then inc(t);
 43     end;
 44     p:=p^.next;
 45   end;
 46   g[x]:=max; if t>0 then inc(g[x]);
 47   if g[x]=0 then inc(g[x]);
 48 end;
 49 //==========================
 50 procedure solve(x,fa:longint);
 51 var
 52   p:ty1;
 53   i,tmp:longint;
 54 begin
 55   p:=first[x];
 56   while p<>nil do
 57   begin
 58     if (p^.x<>fa)and(p^.x<>ms[x]) then
 59     begin
 60       for i:=1 to f[p^.x] do
 61       begin
 62         inc(tot); op[tot]:='M'; s[tot]:=x; t[tot]:=p^.x;
 63       end;
 64       solve(p^.x,x);
 65     end;
 66     p:=p^.next;
 67   end;
 68   if ms[x]>0 then
 69   begin
 70     for i:=1 to f[ms[x]] do
 71     begin
 72       inc(tot); op[tot]:='M'; s[tot]:=x; t[tot]:=ms[x];
 73     end;
 74     solve(ms[x],x);
 75   end;
 76   if x<>y then
 77   begin
 78     for i:=1 to f[x] do
 79     begin
 80       inc(tot); op[tot]:='M'; s[tot]:=x; t[tot]:=fa;
 81     end;
 82   end;
 83 end;
 84 //==========================
 85 begin
 86   assign(input,'catch.in'); reset(input);
 87   assign(output,'catch.out'); rewrite(output);
 88   read(n);
 89   for i:=1 to n-1 do
 90   begin
 91     read(x,y);
 92     insert(x,y); insert(y,x);
 93   end;
 94   min:=maxlongint; y:=0;
 95   for i:=1 to n do
 96   begin
 97     fillchar(g,sizeof(g),0);
 98     fillchar(tms,sizeof(tms),0);
 99     find(i,0);
100     if min>g[i] then
101     begin
102       min:=g[i];
103       f:=g; ms:=tms; y:=i;
104     end;
105   end;
106   writeln(f[y]);
107   for i:=1 to f[y] do
108   begin inc(tot); op[tot]:='L'; s[tot]:=y; end;
109   solve(y,0);
110   writeln(tot);
111   for i:=1 to tot do
112   begin
113     write(op[i],' ');
114     case op[i] of
115     'L':writeln(s[i]);
116     'M':writeln(s[i],' ',t[i]);
117     end;
118   end;
119   close(input); close(output);
120 end.
posted @ 2012-05-31 09:14  datam  阅读(711)  评论(0编辑  收藏  举报