I and OI
Past...

战略游戏(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.

posted on 2011-08-06 16:13  exponent  阅读(552)  评论(0编辑  收藏  举报