poj 1155 TELE(树形DP)

TELE
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 4863   Accepted: 2673

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

/*1是广播总站 ,2到n-m是重转站,n-m+1到n是用户,给出连接两个站或用户之间的费用,以及每个用户愿意出的钱,问在电视台
不亏本的前提下,最多有多少用户可以收看到电视*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <queue>
#include <algorithm>
#include <map>
#include <iomanip>
#define INF 0x3f3f3f3f
#define N 3010
using namespace std;
int n,m;
struct node
{
    int to,w;
    node(int a,int b){to=a,w=b;};
};
vector<node >edge[N*2];
int val[N];
int dp[N][N];//dp[u][j]表示以u为结点,提供给j个用户的的时候最少亏的钱
int dfs(int u,int p)//当前结点,父节点
{
    dp[u][0]=0;
    int ans=0,cut=0;//记录用户的人数,和v是不是用户
    for(int i=0;i<edge[u].size();i++)
    {
        int v=edge[u][i].to;//下一步
        int w=edge[u][i].w;//走这一步需要的费用
        if(v==p) continue;//和父节点重合的时候就跳过
        int cup=dfs(v,u);//v的用户人数
        if(v>=n-m+1)//v是用户不是广播站
        {
            cup++;//u的用户总人数+1
            cut=1;
        }
        else
            cut=0;
        ans+=cup;//u的用户人数
        //cout<<"cup="<<cup<<endl;
        for(int j=min(ans,m);j>=1;j--)//u的用户
        {
            for(int k=min(cup,j);k>=1;k--)//v的用户
            {
                dp[u][j]=min(dp[u][j],dp[u][j-k]+dp[v][k-cut]+w-val[v]);
            }
        }
        
    }
    //cout<<"u="<<u<<" "<<"ans="<<ans<<endl;
    /*dfs出每结点的儿子数没问题*/
    return ans;//输出有几个用户
}
int main()
{
    //freopen("in.txt","r",stdin);
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        int a,b,t;
        for(int i=0;i<=n;i++)
            edge[i].clear();
        memset(val,0,sizeof val);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                dp[i][j]=INF;
        for(int i=1;i<=n-m;i++)
        {
            scanf("%d",&t);
            while(t--)
            {
                scanf("%d%d",&a,&b);
                edge[i].push_back(node(a,b));
                edge[a].push_back(node(i,b));
            }
        }//整理输入
        for(int i=n-m+1;i<=n;i++)
            scanf("%d",&val[i]);
        dfs(1,-1);
        int cur=0;
        for(int i=0;i<=n;i++)
        {
            //cout<<"dp[1][i]="<<dp[1][i]<<endl;
            if(dp[1][i]<=0)
                cur=i;
        }
        printf("%d\n",cur);
    }
    return 0;
}

 

posted @ 2016-08-23 13:16  勿忘初心0924  阅读(192)  评论(0编辑  收藏  举报