zoukankan      html  css  js  c++  java
  • 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
    ",cur);
        }
        return 0;
    }
  • 相关阅读:
    Everything
    图片在下载过程中由模糊逐渐变清晰的技巧
    Windows下Critical Section、Event、Mutex、Semaphores区别
    二维Cookie操作(JS和ASP)
    ASP.net利用urlMappings重写URL路径(URL映射)
    GHOST (以硬盘为单位和以分区分区为单位还原)>个人观点:)
    简单计算器
    ASP操作COOKIE
    擦亮自己的眼睛去看SQLServer之谈谈锁机制
    SQL SERVER2008跟踪标志
  • 原文地址:https://www.cnblogs.com/wuwangchuxin0924/p/5798922.html
Copyright © 2011-2022 走看看