poj 1155 TELE 树形dp ****

TELE
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 3230   Accepted: 1655

Description

A TV-network plans to broadcast an important football match. Their network of transmitters and users can be represented as a tree. The root of the tree is a transmitter that emits the football match, the leaves of the tree are the potential users and other vertices in the tree are relays (transmitters).   The price of transmission of a signal from one transmitter to another or to the user is given. A price of the entire broadcast is the sum of prices of all individual signal transmissions.   Every user is ready to pay a certain amount of money to watch the match and the TV-network then decides whether or not to provide the user with the signal.   Write a program that will find the maximal number of users able to watch the match so that the TV-network's doesn't lose money from broadcasting the match.

Input

The first line of the input file contains two integers N and M, 2 <= N <= 3000, 1 <= M <= N-1, the number of vertices in the tree and the number of potential users.   The root of the tree is marked with the number 1, while other transmitters are numbered 2 to N-M and potential users are numbered N-M+1 to N.   The following N-M lines contain data about the transmitters in the following form:   K A1 C1 A2 C2 ... AK CK   Means that a transmitter transmits the signal to K transmitters or users, every one of them described by the pair of numbers A and C, the transmitter or user's number and the cost of transmitting the signal to them.   The last line contains the data about users, containing M integers representing respectively the price every one of them is willing to pay to watch the match.

Output

The first and the only line of the output file should contain the maximal number of users described in the above text.

Sample Input

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

Sample Output

5

Source

 
题意: 一个电视网络公司,要给尽可能的用户提供TV。但是,其他是不亏本呀。
   1是总站,其他点是  用户  或者是  中转站。
   中转站和用户的点都要钱建立路线,而每个用户出的钱又是不同的。
 
思路: 用一个数组val[ ] 保存 最后各个点的值就可以了。
对于用户的节点:
        val[] = 用户出的钱- 建立线路的钱。
对于中转站的节点:
        val[]= 0  - 建立线路的钱。
 
dp[ k ] [ j ] 表示以k为根节点,给 J 个用户提供TV,盈利的钱。
 
对于叶子节点 dp[ k ] [ 1 ]= val [ k ];
非叶子节点    dp[ k ] [ 0 ]= val [ k ]; //???仔细想一想吧。
 
if( j>=s && dp [ k ] [ j - s ]!= -INF )
dp[ k ] [ j ] = max(  dp [ k ] [ j ]  ,    dp [ k ] [ j - s] + dp [ t ] [ s ])
 
:修改了好久代码,不过写出来,感觉不错。
 
 1 #include<stdio.h>

 2 #include<string.h>

 3 #include<stdlib.h>

 4 #define INF 1000000

 5 int n,m;

 6 int val[3003];

 7 struct node

 8 {

 9     int next[3003];

10     int num;

11 }f[3003];

12 int dp[3003][3003];

13 int Num[3003];

14 

15 int Max(int x,int y)

16 {

17     return x>y? x:y;

18 }

19 

20 void dfs(int k)

21 {

22     int i,j,t,s;

23     if(f[k].num==0)

24         dp[k][1]=val[k];

25     else

26         dp[k][0]=val[k];

27 

28     for(i=1;i<=f[k].num;i++)

29     {

30         t=f[k].next[i];

31         dfs(t);

32         Num[k]+=Num[t];

33     //    printf("%d  Num[k]: %d\n",k,Num[k]);

34    //     system("pause");

35         for(j=Num[k];j>=1;j--)

36         {

37             for(s=1;s<=Num[t];s++)

38             {

39                 if(j>=s && dp[k][j-s]!=-INF)

40                 dp[k][j]=Max(dp[k][j],dp[k][j-s]+dp[t][s]);

41             }

42         }

43     }

44 }

45 

46 int main()

47 {

48     int i,j,t,x,y;

49     while(scanf("%d%d",&n,&m)>0)

50     {

51         memset(val,0,sizeof(val));

52         memset(Num,0,sizeof(Num));

53         for(i=0;i<=n;i++)

54         for(j=0;j<=n;j++)

55         dp[i][j]=-INF;

56         for(i=0;i<=n;i++)

57         f[i].num=0;

58 

59         int k=n-m;

60         for(i=1;i<=k;i++)

61         {

62             scanf("%d",&t);

63             f[i].num=t;

64             Num[t]=0;

65             for(j=1;j<=t;j++)

66             {

67                 scanf("%d%d",&x,&y);

68                 f[i].next[j]=x;

69                 val[x]=-y;

70             }

71         }

72         for(i=n-m+1;i<=n;i++)

73         {

74             scanf("%d",&x);

75             val[i]=val[i]+x;

76             Num[i]=1;

77         }

78         val[1]=0;

79         dfs(1);

80         for(i=m;i>=1;i--)

81         {

82             if(dp[1][i]>=0)

83             {

84                 printf("%d\n",i);

85                 break;

86             }

87         }

88     }

89     return 0;

90 }

 

 
 
 
 

你可能感兴趣的:(poj)