战略游戏(SGOI)
stragedi.pas/c/cpp
【问题描述】
Bob 喜欢玩电脑游戏,特别是战略游戏。但是他经常无法找到快速玩过游戏的办法。现在他有个问题。他要
建立一个古城堡,城堡中的路形成一棵树。他要在这棵树的结点上放置最少数目的士兵,使得这些士兵能了望到
所有的路。注意,某个士兵在一个结点上时,与该结点相连的所有边将都可以被了望到。
请你编一程序,给定一树,帮 Bob 计算出他需要放置最少的士兵。
【输入格式】
输入文件中数据表示一棵树,描述如下:
第一行 N,表示树中结点的数目。
第二行至第 N+1 行,每行描述每个结点信息,依次为:该结点标号 i,k(后面有 k 条边与结点 I 相连),
接下来 k 个数,分别是每条边的另一个结点标号 r1,r2,...,rk。
对于一个 n(0 < n <= 1500)个结点的树,结点标号在 0 到 n-1之间,在输入文件中每条边只出现一次。
【输出格式】
输出文件仅包含一个数,为所求的最少的士兵数目。
【输入样例1】
4
0 1 1
1 2 2 3
2 0
3 0
【输出样例1】
1
【输入样例2】
5
3 3 1 4 2
1 1 0
2 0
0 0
4 0
【输出样例2】
2
【时间限制】
1s
【空间限制】
64M
//-------------------------------------------------------------------------------------
分析:比较简单的树规,f[i,0..1]表示第i个节点放或不放士兵,以i为根的子树所需的最少人数.
设s为i的一个儿子,则f[i,0]必须从f[s,1]转移而来,f[i,1]可以从f[s,0]或f[s,1]转移来.
code:
type edge=record v,n:longint; end; const maxn=1501; var e:array[0..maxn] of edge; r,h:array[0..maxn] of longint; f:array[0..maxn,0..1] of longint; n,i,j,q,u,v,root,cnt:longint; procedure add(u,v:longint); begin inc(cnt); e[cnt].v:=v; e[cnt].n:=h[u]; h[u]:=cnt; end; function min(a,b:longint):longint; begin if a>b then exit(b); exit(a); end; procedure DP(u:longint); var v,p:longint; begin f[u,0]:=0; f[u,1]:=1; p:=h[u]; while p<>0 do begin v:=e[p].v; DP(v); inc(f[u,0],f[v,1]); inc(f[u,1],min(f[v,0],f[v,1])); p:=e[p].n; end; end; begin assign(input,'stragedi.in'); reset(input); assign(output,'stragedi.out'); rewrite(output); readln(n); for i:=1 to n do begin read(u); read(q); for j:=1 to q do begin read(v); add(u,v); inc(r[v]); end; readln; end; for i:=0 to n-1 do if r[i]=0 then begin root:=i; break; end; DP(root); writeln(min(f[root,0],f[root,1])); close(input); close(output); end.