题意:给出n个节点的树,根节点是电视台,给出m个用户,用户的编号为(n-m+1,n)

    接下来给出n-m+1行,第一行就是以编号为1为向其他点连接,第二行就是以编号为2向其他点连接,以此类推

      然后在处理某一行的时候,第一个数字表示有多少个儿子

        然后接下来每次输入两个数,第一个为编号,第二个为边权值

    最后一行给出用户给出的费用

    问在不亏本的情况下所能连接的最多用户为多少

思路:不亏本,即为最后花费的钱数<=0

    首先确立dp【i】【j】表示在第i颗树时,有j个用户的最少花费

      那么我们遍历某个节点的时候,就从当前最大的节点数开始更新,为什么不能从最小呢?

        因为倘若从最小开始的话呢,可能会重复使用某个用户(这跟背包类似)

          然后逐一遍历即可

好久没有自己做出树形DP了!!!这道题让我挺开心,虽然是道没有什么修饰的题

P1273 有线电视网_DPP1273 有线电视网_i++_02
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=3e3+10;
 4 const int inf=0x3f3f3f3f;
 5 int dp[maxn][maxn];
 6 struct node
 7 {
 8     int v,w,nxt;
 9 }G[maxn];
10 int head[maxn]; int num;
11 int sum[maxn];
12 void add(int u,int v,int w)
13 {
14     G[++num].v=v;G[num].w=w;G[num].nxt=head[u];head[u]=num;
15 }
16 void dfs(int u)
17 {
18   //  printf("u:%d\n",u);
19     for(int T=head[u];T;T=G[T].nxt){
20         int v=G[T].v;int w=G[T].w;
21        // printf("2222222222\n");
22         dfs(v);
23         int tmp=sum[u]+sum[v];
24         for(int i=tmp;i>=1;i--)
25             for(int j=0;j<=sum[u];j++){
26                 int k=i-j;
27                 if(k>sum[v]) continue;
28                 dp[u][i]=min(dp[u][i],dp[u][j]+dp[v][k]+w);
29               //  printf("dp[%d][%d]:%d\n",u,i,dp[u][i]);
30                // printf("dp[%d][1]: %d\n",v,dp[v][1]);
31             }
32         sum[u]+=sum[v];
33     }
34 }
35 int main()
36 {
37     int n,m;
38     scanf("%d%d",&n,&m);
39     for(int i=1;i<=n-m;i++){
40         int k;
41         scanf("%d",&k);
42         int u=i;
43         for(int j=1;j<=k;j++){
44             int v,w;
45             scanf("%d%d",&v,&w);
46             add(u,v,w);
47         }
48     }
49     memset(dp,inf,sizeof(dp));
50     for(int i=1;i<=n;i++)
51         dp[i][0]=0;
52     for(int i=n-m+1;i<=n;i++){
53         int tmp;
54         scanf("%d",&tmp);
55         dp[i][1]=-tmp;
56         sum[i]=1;
57     }
58     dfs(1);
59    // printf("%d\n",dp[1][1]);
60     for(int i=m;i>=0;i--){
61         if(dp[1][i]<=0){
62             printf("%d\n",i);
63             break;
64         }
65     }
66     return 0;
67 }
View Code