题目

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

输入格式

输入的第一行是一个正整数\(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\)之间有一条不经过其它城镇的双向道路。输入数据保证所有城镇是连通的。

输出格式

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

输入样例

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

输出样例

9
solution is unique

样例解释

最佳路线包括城镇 1,2, 4, 5, 9

题解

任意两个城镇之间都只有唯一的可能经过其它城镇的路线,说明这一定是一棵树

第一问

这道题明显是树形动规,但加了一个限制条件,就是最大停留次数,联想树形动规时的形式,这个最大停留次数其实和能访问的子树个数有关系.

上图表示了一个DFS过程,其中2,3,4,5,6号都是子树,若将这些子树看成一个点,则DFS过程中经过的节点为

[1] 2 [1] 2 [1] 4 [1] 5 [1] 6 [1]

注意其中的根节点1,出现了6次,本题中就是停留了6次,而1号节点有5棵子树,可以发现,若i节点最大停留次数为\(limit[x]\),则DFS中最多能访问\(limit[x]-1\)棵子树

这些子树中对根节点dp的贡献不同,我们当然要选择其中最大的,所以排一下序,选其中前\(limit[x]-1\)棵子树来更新根节点的dp值.

注意,\(limit[x]-1\)也存在大于子树个数的情况,所以实际操作的时候要取\(limit[x]\)和字数个数的最小值作为更新根节点的子树数量,由于净收益可能是负数,所以更新的时候发现是负数立刻停止即可.

所以遍历子树(已排序)时候,条件为

soni < min(limit[root] - 1, sontot) && dp[sonn[soni + 1]] >= 0

其中,soni为当前循环遍历的子树时的循环变量(注意不时子树根节点编号),root为根节点编号,sontot为子树的数量,sonn数组保存子树的根节点编号,sonn[soni+1]为这次循环的子树编号(因为soni在循环内自增1)

还有一个条件

家乡对小T当然没有停留次数的限制

也就是整棵树的根节点无限制次数,那么只需要在DFS之前将根节点的limit值赋值为无限大即可

第二问

显然,根节点方案是否唯一首先要看其子树,如果有任意一棵更新了根节点dp值得子树的方案不唯一,根节点的方案显然也不唯一.

除此之外,还有存在子树方案唯一但根节点选取子树的方案不唯一的情况.

遍历子树的时候,将 子树方案是否唯一的值 和 根节点选取子树的方案是否唯一 的值进行或运算(只要有一个为真,结果就为真),得到的结果就是这棵树的方案是否唯一,最后输出即可.

那么怎么判断根节点选取子树的方案是否唯一呢,有两种情况:

  1. 相同值引起的不唯一

假设排好序后的子树dp值为10 9 8 7 6 6 5 4 3 2 1,而你只能选5个(limit值为6),显然你选择的是10 9 8 7 6,但是仔细观察,你会发现还有一个相同的6,那么我能不能抛弃第一个6选择第二个6呢?当然可以,那么,这就有了两种选择办法([10] [9] [8] [7] [6] 6 5 4 3 2 1[10] [9] [8] [7] 6 [6] 5 4 3 2 1)

  1. dp值为0引起的不唯一

假设排好序后的子树dp值为10 9 8 7 6 0,而你只能选5个(limit值为6),你可以选择10 9 8 7 6,也可以选择10 9 8 7 6 0,这两种方案更新的值都是一样的.

出现这两种情况时,直接将这棵树方案是否唯一的赋值为真即可

代码

#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 100000;
struct edge {
    int i, next;
} edges[2 * N + 5];
int head[N + 5], tot, n, w[N + 5], limit[N + 5], dp[N + 5], ansn[N + 5],sonn[N + 5];
void add(int u, int v) {
    edges[++tot].i = v;
    edges[tot].next = head[u];
    head[u] = tot;
}
bool cmp(int a, int b) { return dp[a] > dp[b]; }
void dfs(int root, int f) {
    dp[root] = w[root];
    int sontot = 0, soni = 0;
    for (int i = head[root]; i; i = edges[i].next)
        if (edges[i].i != f) dfs(edges[i].i, root);
    for (int i = head[root]; i; i = edges[i].next)
        if (edges[i].i != f) sonn[++sontot] = edges[i].i;
    sort(sonn + 1, sonn + 1 + sontot, cmp);
    while (soni < min(limit[root] - 1, sontot) && dp[sonn[soni + 1]] >= 0)
        dp[root] += dp[sonn[++soni]], ansn[root] |= ansn[sonn[soni]];//按位或
    if (soni < sontot && soni > 0 && dp[sonn[soni]] == dp[sonn[soni + 1]] || dp[sonn[soni]] == 0 && soni > 0)//两种情况,注意边界
        ansn[root] = 1;
}
int main() {
    scanf("%d", &n);
    for (int i = 1; i < n; i++) scanf("%d", &w[i + 1]);
    for (int i = 1; i < n; i++) scanf("%d", &limit[i + 1]);
    for (int i = 1; i < n; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        add(u, v);
        add(v, u);
    }
    limit[1] = n + 1;//在家乡没有停留限制
    dfs(1, 0);
    printf("%d\n%s", dp[1], ansn[1] ? "solution is not unique" : "solution is unique");
    return 0;
}

BZOJ 4472 salesman 题解的更多相关文章

  1. bzoj 4472 salesman

    Written with StackEdit. Description 某售货员小\(T\) 要到若干城镇去推销商品,由于该地区是交通不便的山区,任意两个城镇 之间都只有唯一的可能经过其它城镇的路线. ...

  2. 【树形dp】 Bzoj 4472 Salesman

    题目 某售货员小T要到若干城镇去推销商品,由于该地区是交通不便的山区,任意两个城镇 之间都只有唯一的可能经过其它城镇的路线. 小T 可以准确地估计出在每个城镇停留的净收 益.这些净收益可能是负数,即推 ...

  3. BZOJ 1179 Atm 题解

    BZOJ 1179 Atm 题解 SPFA Algorithm Tarjan Algorithm Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来 ...

  4. BZOJ 4472 [Jsoi2015]salesman(树形DP)

    4472: [Jsoi2015]salesman Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 417  Solved: 192[Submit][St ...

  5. bzoj 4472: [Jsoi2015]salesman【树形dp+贪心】

    一个点,设f[u]为要取最大值显然是前最大停留次数-1个儿子的正数f和,排个序贪心即可 判重的话就是看没选的里面是否有和选了的里面f值相同的,有的话就是一.注意在选的时候要把加进f的儿子的g合并上去 ...

  6. BZOJ 4236~4247 题解

    BZOJ 4236 JOIOJI f[i][0..2]表示前i个字符中′J′/′O′/′I′的个数 将二元组<f[i][0]−f[i][1],f[i][1]−f[i][2]>扔进map,记 ...

  7. Bzoj 2064 分裂 题解

    2064: 分裂 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 570  Solved: 350[Submit][Status][Discuss] De ...

  8. Bzoj 2288 生日礼物题解

    2288: [POJ Challenge]生日礼物 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 856  Solved: 260[Submit][S ...

  9. [CQOI2007]涂色paint(BZOJ 1260)题解

    题目描述 假设你有一条长度为5的木版,初始时没有涂过任何颜色.你希望把它的5个单位长度分别涂上红.绿.蓝.绿.红色,用一个长度为5的字符串表示这个目标:RGBGR. 每次你可以把一段连续的木版涂成一个 ...

随机推荐

  1. Ado.net 02

    1.连接字符串不同,连接池也不同 SqlConnection对象只能被打开一次.但是在Close()后再进行Open()操作.但是在Dispose()之后就不能再Open()了. 2.SqlDataA ...

  2. 移动端overflow失效问题

    在项目开发中,我们有时候需要实现元素从屏幕外移动到屏幕内的效果. 我们一般会有这样的方案:先通过position: absolution或transform: translate() 使得元素移动到屏 ...

  3. DOM是什么(初级版)

    js新手村出村之路--基础知识 在这里默认你已经粗粗的自学过了一遍js知识.(也许是在昏昏欲睡的课堂上听了两分钟,也许是跟着b站上的视频打了一遍.who cares) 在下面的内容中我将整理一些在平常 ...

  4. 使用vue cli3新建一个vue项目

    写在最前 虽然身为一个java后端工作者,前端还是要沾点的,基于vue的火热,所以平常的工作中项目前端基本都是vue.这次就主要讲一讲vue项目的创建,并从vue的安装开始讲起,附带上我之前安装使用时 ...

  5. 5G 将带给程序员哪些新机会呢?

    5G,第 5 代移动通信技术,华为在此领域远远领先同行,这也让它成了中美贸易战的最前线.我的第一份工作就在通信行业,当时电信标准都在欧美企业手里,国内企业主要是遵照标准研发软硬件设备,核心芯片靠进口. ...

  6. windows 下载~安装nginx

    nginx 中文文档 http://www.nginx.cn/doc/ 到nginx官网下载安装包http://nginx.org/en/download.html 解压安装包 进入windows的c ...

  7. php 生成游戏兑换码(礼包)方法

    最近项目中要做礼包码生成,看了看网上的代码,可以使用php扩展unid 当然我这里并不是用的unid,而是使用的php自带的uniqid,人狠话不多.看代码 /** * 生成礼包接口 100W数据同时 ...

  8. watch 同步表单 记得$nextTick,否则不会同步更新到组件内

    watch 同步表单 记得$nextTick,否则不会同步更新到组件内 watch: { 'formData.aaa' (val) { this.$nextTick(() => { this.f ...

  9. echarts legend文字配置多个颜色(转)

    困扰很久的问题终于解决了 oh yea! echarts legend文字配置多个颜色legend: {data: [{name:‘直接访问’,icon : ‘circle’,textStyle: { ...

  10. Block详解二(底层分析)

    Block专辑: Block讲解一 MRC-block与ARC-block Block详解一(底层分析) 今天讲述Block的最后一篇,后两篇仅仅是加深1,2篇的理解,废话少说,开始讲解! __blo ...