I and OI
Past...

比赛转播
tele.pas/c/cpp
【问题描述】
一个电视网络计划转播一场重要的足球比赛。网络中的传输点和接收点(即用户)可以表示一棵树。这棵树
的根是一个传输点,它将转播比赛。树的叶节点是可能要接受这场比赛的用户(他当然可以选择不看比赛,这样
就不要交款)。其他非根节点,非叶节点的中间节点为数据的中转站。 
将一个信号从一个传输点传到另一个传输点的花费是给定的。整个转播的费用就是每一个传输费用的总和。  
每一个用户(叶节点)都准备付一定的钱来看这场比赛。电视网络公司要决定是否要给这个用户提供电视信
号。例如:给一个节点传输信息的花费太大,而他愿意的付款也很少时,网络公司可能选择不给他转播比赛。 
写一个程序,找一个传输方案使最多的用户能看到转播比赛,且转播的费用不超过所有接收信号用户的交款。  
【输入格式】
输入文件的第一行包含两个整数N和M(2<=N<=3000,1<=M<=N-1)。N,M表示分别表示树的节点数和想观看比
赛的用户数。树的根节点用1表示,中间节点的标号为2~N-M,用户的节点标号为N-M+1~N。 
接下来的N-M行表示传输点的信息(依次是节点1,2……): 
K A1 C1 A2 C2 …… Ak Ck
表示一个传输点将信号传给K个用户,每一个包含两个数A和C, A表示传输点或用户的节点号, C表示传输的花

费。  
最后一行含有用户的数据,有M个整数表示他们看这场比赛愿意的付费。 
【输出格式】
仅一行包含一个整数,最大的用户数。 
【输入样例1】
5 3 
2 2 2 5 3 
2 3 2 4 3 
3 4 2 
【输出样例1】

【输入样例2】
5 3 
2 2 2 5 3 
2 3 2 4 3 
4 4 2 
【输出样例2】

【输入样例3】
9 6 
3 2 2 3 2 9 3 
2 4 2 5 2 
3 6 2 7 2 8 2 
4 3 3 3 1 1  
【输出样例3】

【时间限制】
1s
【空间限制】
128M

//-----------------------------------------------------------------------------------------------

分析:将中间节点的权值设为负的,就可以用树形依赖背包做了,对于叶子节点特殊处理下就好了.

code:

type  edge=record
      v,n:longint;
end;
const oo=100000000;
      root=1;
var   f:array[0..3000,0..3000] of longint;
      cost,h:array[0..3000] of longint;
      e:array[0..3000] of edge;
      n,m,i,j,t,x,y,value,ans,cnt:longint;

      function max(a,b:longint):longint;
      begin
            if a>b then exit(a); exit(b);
      end;

      procedure add(u,v:longint);
      begin
            inc(cnt);
            e[cnt].v:=v;
            e[cnt].n:=h[u];
            h[u]:=cnt;
      end;

      procedure dfs(u,c:longint);
      var   v,p,o:longint;
      begin
            p:=h[u];
            if p=0 then
              for o:=c+1 downto 1 do f[u,o]:=f[u,o-1];

            while p<>0 do
            begin
                  v:=e[p].v;
                  for o:=0 to c do f[v,o]:=f[u,o];
                  dfs(v,c-1);
                  for o:=0 to c do
                     f[u,o]:=max(f[u,o],f[v,o]-cost[v]);
                  p:=e[p].n;
            end;
      end;

begin
      assign(input,'tele.in'); reset(input);
      assign(output,'tele.out'); rewrite(output);

      readln(n,m);
      for i:=1 to n-m do
      begin
            read(t);
            for j:=1 to t do
            begin
                  read(x,y);
                  add(i,x);
                  cost[x]:=y;
            end;
            readln;
      end;

      for i:=n-m+1 to n do
      begin
            read(value);
            dec(cost[i],value);
      end;

      for i:=1 to n do
         for j:=0 to m do f[i,j]:=-oo;

      f[root,0]:=0;

      dfs(root,m);
      for ans:=m downto 0 do
         if f[root,ans]>=0 then break;

      writeln(ans);

      close(output);
end.

posted on 2011-08-07 08:43  exponent  阅读(605)  评论(0编辑  收藏  举报