zoukankan      html  css  js  c++  java
  • bzoj 4472: [Jsoi2015]salesman

    4472: [Jsoi2015]salesman

    链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4472

    Time Limit: 10 Sec  Memory Limit: 128 MB

    Description

    某售货员小T要到若干城镇去推销商品,由于该地区是交通不便的山区,任意两个城镇
    之间都只有唯一的可能经过其它城镇的路线。 小T 可以准确地估计出在每个城镇停留的净收
    益。这些净收益可能是负数,即推销商品的利润抵不上花费。由于交通不便,小T经过每个
    城镇都需要停留,在每个城镇的停留次数与在该地的净收益无关,因为很多费用不是计次收
    取的,而每个城镇对小T的商品需求也是相对固定的,停留一次后就饱和了。每个城镇为了
    强化治安,对外地人的最多停留次数有严格的规定。请你帮小T 设计一个收益最大的巡回方
    案,即从家乡出发,在经过的每个城镇停留,最后回到家乡的旅行方案。你的程序只需输出
    最大收益,以及最优方案是否唯一。方案并不包括路线的细节,方案相同的标准是选择经过
    并停留的城镇是否相同。因为取消巡回也是一种方案,因此最大收益不会是负数。小T 在家
    乡净收益是零,因为在家乡是本地人,家乡对小 T当然没有停留次数的限制。

    Input

    输入的第一行是一个正整数n(5<=n<=100000),表示城镇数目。城镇以1到n的数命名。小T 的家乡命
    名为1。第二行和第三行都包含以空格隔开的n-1个整数,第二行的第i个数表示在城镇
    i+1停留的净收益。第三行的第i个数表示城镇i+1规定的最大停留次数。所有的最大
    停留次数都不小于2。接下来的n-1行每行两个1到n的正整数x,y,之间以一个空格
    隔开,表示x,y之间有一条不经过其它城镇的双向道路。输入数据保证所有城镇是连通的。 

    Output

    输出有两行,第一行包含一个自然数,表示巡回旅行的最大收益。如果该方案唯一,在
    第二行输出“solution is unique”,否则在第二行输出“solution is not unique”。

    Sample Input

    9
    -3 -4 2 4 -2 3 4 6
    4 4 2 2 2 2 2 2
    1 2
    1 3
    1 4
    2 5
    2 6
    3 7
    4 8
    4 9

    Sample Output

    9
    solution is unique
    //最佳路线包括城镇 1,2, 4, 5, 9。
     
    题解:树形dp, dp[i]表示i的子树可获得的最大利,dp[u] = sum(dp[v] ,dp[v] >= 0) 且只能选c[i] - 1个;要一个优先队列就可以了, 注意判方案数重;
    建双向边
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 100005;
    #define inf 10000008
    int tot, head[maxn],dp[maxn],c[maxn];
    int uni[maxn];
    struct edge{
        int v,nxt;
    }G[maxn * 2 +50];
    struct ins{
        int to, co;
        bool operator < (const ins &a)const{
            return a.co > co;
        }
    };
    priority_queue <ins> q[maxn];
    void add(int u, int v){
        G[++tot].nxt = head[u];
        G[tot].v = v;
        head[u] = tot;
    }
    void dfs(int u, int fa){
        for(int i = head[u]; i; i = G[i].nxt){
            int v = G[i].v;
            if(v == fa)continue;
            dfs(v, u);
            q[u].push((ins){v,dp[v]});
        }
        int tt = 0, last = -1;
        while(!q[u].empty() && tt < c[u]-1){
            ins top = q[u].top();
            if(top.co >= 0) {
                if(!top.co)uni[u] = 1;
                tt++;
                uni[u] = uni[u] | uni[top.to];
                dp[u] += top.co;
                last = top.co;
                q[u].pop();
            }
            else break;
        }
        if(!q[u].empty() && last != -1)
            if(q[u].top().co == last)uni[u] = 1;
    }
    int main(){
        int n;
        scanf("%d",&n);
        for(int i = 2; i <= n; i++)
            scanf("%d",&dp[i]);
        c[1] = inf;
        for(int i = 2; i <= n; i++)
            scanf("%d",&c[i]);
        for(int i = 1; i < n; i++){
            int u, v;
            scanf("%d%d",&u,&v);
            add(u, v);
            add(v, u);
        }
        dfs(1, 1);
        cout<<dp[1]<<endl;
        if(uni[1])cout<<"solution is not unique"<<endl;
        else cout<<"solution is unique"<<endl;
    }
  • 相关阅读:
    对象与内存控制1---实例变量和类变量
    数组与内存控制2--数组使用
    数组与内存控制1--数组初始化
    Java 三大特征之--多态
    简述Java面向对象三大特征:封装、继承、多态
    java程序初始化的顺序
    关于public static void main(String[] args)相关知识
    Java的优点
    前端面试攻略3------HTML和CSS部分
    前端面试攻略2------计算机网络部分
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/8474504.html
Copyright © 2011-2022 走看看