题意:给你一棵树,要选择若干节点,若一个点i没有选择,则有\(d(dis(i,j))\)的代价,其中j被选择。选择一个点代价为k,求最小代价。

首先,考虑这样一个问题:

如果距离a的最近被选点为i,距离b的最近被选点也是i,那么a到b的路径上的点的最近被选点都是i。

考虑一条链:设Ax是链上第x个点,那么点y到Ax的距离fy(x)随x的增加,先下降,再上升。(这个显然)。

那么假设a到b路径上的c,最近点不是i而是j。

那么,\(dis(a,i)<dis(a,j),dis(c,i)>dis(c,j),dis(b,i)<dis(b,j)\)。

就是说\(fi\)和\(fj\)有两个交点。但这是不可能的。

所以,如果距离a的最近被选点为i,距离b的最近被选点也是i,那么a到b的路径上的点的最近被选点都是i一定成立。

换句话说,以i为最近点的j是一个连通块。

这样,我们设\(dp(i,j)\)表示i的最近点是j的状态。再维护\(f(i)\)表示\(dp(i,j)\)的最小值。

那么,对于i的每个儿子v,枚举它的最近点a,则转移到\(dp(v,a)\)。

但如果\(j=a\),那么对于v来说,a已经选择过了,则转移到\(dp(v,a)-k\)。

维护\(f(i)\)后就是\(dp(i,j)=min(f(v),dp(v,j)-k)+d(dis(i,j))+k\)。

因为要输出方案,再记录一下转移的位置。

\(dis\)数组可以\(O(n^2)\)预处理出。

代码:

#include <stdio.h>
int fr[182],ne[362],v[362],bs = 0;
void addb(int a, int b) {
v[bs] = b;
ne[bs] = fr[a];
fr[a] = bs++;
}
int dp[182][182],wz[182],sz[182],cd[182][182],n,k;
int fa[182],sd[182],ans[182],zy[362][182];
void dfs0(int u, int f) {
fa[u] = f;
sd[u] = sd[f] + 1;
for (int i = fr[u]; i != -1; i = ne[i]) {
if (v[i] != f) dfs0(v[i], u);
}
}
int dfscd(int a, int b) {
if (a == b) return 0;
if (cd[a][b]) return cd[a][b];
if (sd[a] > sd[b]) cd[a][b] = dfscd(fa[a], b) + 1;
else cd[a][b] = dfscd(a, fa[b]) + 1;
return cd[a][b];
}
void dfs(int u, int f) {
for (int i = fr[u]; i != -1; i = ne[i]) {
if (v[i] != f) dfs(v[i], u);
}
for (int a = 1; a <= n; a++) {
dp[u][a] = sz[cd[u][a]] + k;
for (int i = fr[u]; i != -1; i = ne[i]) {
if (v[i] == f) continue;
int t = dp[v[i]][wz[v[i]]];
if (dp[v[i]][a] - k < t) {
t = dp[v[i]][a] - k;
zy[i][a] = a;
} else zy[i][a] = wz[v[i]];
dp[u][a] += t;
}
if (a == 1 || dp[u][a] < dp[u][wz[u]]) wz[u] = a;
}
}
void dfs1(int u, int f, int a) {
ans[u] = a;
for (int i = fr[u]; i != -1; i = ne[i]) {
if (v[i] != f) dfs1(v[i], u, zy[i][a]);
}
}
int main() {
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++) fr[i] = -1;
for (int i = 1; i < n; i++) scanf("%d", &sz[i]);
for (int i = 0; i < n - 1; i++) {
int a,b;
scanf("%d%d", &a, &b);
addb(a, b);
addb(b, a);
}
dfs0(1, 0);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (i != j && cd[i][j] == 0) dfscd(i, j);
}
}
dfs(1, 0);
int z = 1;
for (int i = 2; i <= n; i++) {
if (dp[1][i] < dp[1][z]) z = i;
}
printf("%d\n", dp[1][z]);
dfs1(1, 0, z);
for (int i = 1; i <= n; i++) printf("%d ", ans[i]);
return 0;
}

CF70E Information Reform的更多相关文章

  1. 用信息值进行特征选择(Information Value)

    Posted by c cm on January 3, 2014 特征选择(feature selection)或者变量选择(variable selection)是在建模之前的重要一步.数据接口越 ...

  2. iOS之使用模拟器报错:resource fork, Finder information, or similar detritus not allowed

    很奇怪的问题,使用真机测试没有问题.但使用模拟器测试的时候就会报这样的错误,错误类型为:Code Sign Error 错误提示是这样:resource fork, Finder informatio ...

  3. Information Management Policy(信息管理策略)的使用范例

    基础知识 很多人都会定期收拾自己的书架或者抽屉,把里面过旧的资料拿走,为新的资料腾出空间来,这样既可以节省空间,而且当冗余资料过多的时候也会降低你查找的速度和效率.那么,在企业的SharePoint中 ...

  4. Android Studio安装以及Fetching android sdk component information超时的解决方案

    转载:http://www.cnblogs.com/sonyi/p/4154797.html 在经过两年的开发之本后,Google 公司终于发布了 Android Studio 1.0,喜欢折腾的童鞋 ...

  5. iOS Xcode, 解决“Could not insert new outlet connection: Could not find any information for the class named”的问题。

    在Xcode中,我们可以在StoryBoard编辑界面或者是xib编辑界面中通过“Control键+拖拽“的方式将某个界面元素和对应的代码文件连接起来,在代码文件中创建outlet. 不过,如果你的运 ...

  6. ORA-00824: cannot set sga_target due to existing internal settings, see alert log for more information

    这篇文章是上篇文章”Expdp 导数错误 ORA-00832”的延续,前几天工作比较忙.累,直到今天才整理发出来.这个数据库实例的参数设置比较诡异其实是有原因的,由于这台数据库服务器系统是32位,数据 ...

  7. MS SQL Could not obtain information about Windows NT group/user 'domain\login', error code 0x5. [SQLSTATE 42000] (Error 15404)

    最近碰到一个有趣的错误:海外的一台数据库服务器上某些作业偶尔会报错,报错信息如下所示: -------------------------------------------------------- ...

  8. MS SQL错误:SQL Server failed with error code 0xc0000000 to spawn a thread to process a new login or connection. Check the SQL Server error log and the Windows event logs for information about possible related problems

          早晨宁波那边的IT人员打电话告知数据库无法访问了.其实我在早晨也发现Ignite监控下的宁波的数据库服务器出现了异常,但是当时正在检查查看其它服务器发过来的各类邮件,还没等到我去确认具体情 ...

  9. Could not obtain information about Windows NT group/user 'xxxx\xxxx', error code 0x5

    案例描述 昨晚踢球回来,接到电话说一个系统的几个比较重要作业出错,导致系统数据有些问题.让我赶紧检查看看.检查作业日志时发现,作业报如下错误(关键信息用xxx替换) The job failed.  ...

随机推荐

  1. wordpress 后台无法登录 网站内容缺失

    昨天网站又突然不正常了,前两天都是好的.. 具体来说就是wp后台登录不进去,一直在登录页跳转,与此同时服务器上其他网站也有这个问题,而且有些网站的板块内容也缺失了, 所以首要就是要登录进后台看看是不是 ...

  2. Linux驱动函数解读

    一.kmalloc().kzalloc()和vmalloc() 这三个函数都可以分配连续的虚拟内存 除此之外,这三个函数的区别有: 1. kmalloc()和kzalloc()函数分配的物理内存也是连 ...

  3. const关键字的使用——C语言

    一.常规用法 关键字const用来定义只读变量,被const定义的变量它的值是不允许改变的,即不允许给它重新赋值,即使是赋相同的值也不可以.所以说它定义的是只读变量,这也就意味着必须在定义的时候就给它 ...

  4. python练习:函数2

    习题: 定义一个方法get_num(num),num参数是列表类型,判断列表里面的元素为数字类型.其他类型则报错,并且返回一个偶数列表:(注:列表里面的元素为偶数). def get_num(num) ...

  5. Python练习_集合和深浅拷贝_day7

    1. 1.作业 1.把列表中所有姓周的人的信息删掉(升级题:此题有坑, 请慎重): lst = ['周老二', '周星星', '麻花藤', '周扒皮'] 结果: lst = ['麻花藤'] 2.车牌区 ...

  6. JVM学习笔记——类加载过程

    JVM学习笔记——类加载过程 类加载模型——双亲委派模型(Parents Delegation Model)也可称为“溯源委派加载模型” Java的类加载器是一个运行时核心基础设施模块,主要是启动之初 ...

  7. webpack如何使用vue

    1.安装vue的包:  cnpm i vue -S 2.在main.js中导入包 3.运行起来报错 3.1第一种解决办法: 3.2第二种解决办法: 让我们先回顾一下包的查找规则: //1.找项目根目录 ...

  8. python日志实时分析

    python随着人工智能的发展,越来越火热.但其实python在运维测试方面,也是一把利器. 最近就碰到了个需求,就顺手写了个python程序.用惯了go,不过发现python好像更简单点 :-) 涉 ...

  9. Apache Log View 5.37破解笔记

    i春秋作家:Sp4ce 之前说过要分享这个日志分析工具[记一次简单的攻击日志分析]的破解版,在破解的路上踩了几个坑,记录分享下. 0×00程序概述 原程序 大小: 2283672 字节文件版本: 5. ...

  10. stm32 窗口看门狗 WWDG

    窗口看门狗WWDG其实和独立看门狗类似,它是一个7位递减计数器不断的往下递减计数,当减到一个固定值0x40时还不喂狗的话,产生一个MCU复位,这个值叫窗口的下限,是固定的值,不能改变 窗口看门狗(WW ...