题解 P2726 【[SHOI2005]树的双中心】

news/2024/10/1 23:44:10

首先,我们会有一个很简单的想法,枚举断边,产生两棵子树,然后在两棵树内分别求带权重心,计算贡献,这样的话复杂度是 \(O(n^2)\) 的。

那么我们要好好利用 $h \leq 100 $ 的性质。

考虑 \(sze[u]\) 为带权重量,\(g[u]\) 为以 \(u\) 为根的树,所有点都到 \(u\) 的代价。

所以 \(g[u] = \sum\limits_{v\in{son(u)}}{g[v] + sze[v]}\)

考虑 \(f[u]\)\(u\) 在的一棵树中,所有点到 \(u\) 的总代价。

由于计算是动态的,我们考虑转移。

对于 \(v \in son(u)\)\(f[v] = f[u] + (S - sze[v]) - sze[v]\)

如果 \(v\)\(u\) 更优,当且仅当 \(2 * sze[v] > S\)

我们发现,只有两个候选项,重儿子和次重儿子。递归时顺带维护变化即可。

最坏情况可能会是一条到底的链,所以复杂度 \(O(nh)\)

code:

const int Maxn = 5e5 + 5, Maxm = 1e6 + 5;
int n, cnt = 0, w[Maxn], head[Maxn], ver[Maxm], nxt[Maxm];
inline void AddEdge(int u, int v) {ver[++cnt] = v, nxt[cnt] = head[u], head[u] = cnt;ver[++cnt] = u, nxt[cnt] = head[v], head[v] = cnt;
}int dep[Maxn], fat[Maxn], son[Maxn], son2[Maxn];
int sze[Maxn], g[Maxn], cut, ans = INT_MAX;
inline void DfsFir(int u) {sze[u] = w[u];for (int i = head[u]; i; i = nxt[i]) {if (ver[i] == fat[u]) continue;dep[ver[i]] = dep[u] + 1; fat[ver[i]] = u;DfsFir(ver[i]); sze[u] += sze[ver[i]];g[u] += g[ver[i]] + sze[ver[i]];if (sze[ver[i]] > sze[son[u]]) son2[u] = son[u], son[u] = ver[i];else if (sze[ver[i]] > sze[son2[u]]) son2[u] = ver[i];}
}inline void getans(int u, int val, int all, int &ret) {chkmin(ret, val); int v = son[u];if (v == cut || sze[son[u]] < sze[son2[u]]) v = son2[u];if (!v) return;if (2 * sze[v] > all) getans(v, val + all - 2 * sze[v], all, ret);
}inline void DfsSec(int u) {for (int i = head[u]; i; i = nxt[i]) {if (ver[i] == fat[u]) continue;cut = ver[i]; int x = INT_MAX, y = INT_MAX;for (int pos = u; pos; pos = fat[pos]) sze[pos] -= sze[ver[i]];getans(1, g[1] - g[ver[i]] - dep[ver[i]] * sze[ver[i]], sze[1], x);getans(ver[i], g[ver[i]], sze[ver[i]], y); chkmin(ans, x + y);for (int pos = u; pos; pos = fat[pos]) sze[pos] += sze[ver[i]];DfsSec(ver[i]);}
}signed main(void) {
//	file("");read(n);for (int i = 1, u, v; i < n; i++)read(u), read(v), AddEdge(u, v);for (int i = 1; i <= n; i++) read(w[i]);DfsFir(1); DfsSec(1); writeln(ans);
//	fwrite(pf, 1, o1 - pf, stdout);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/66975.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

dedecms(织梦)网站安全防护设置

织梦CMS 是国内常用的免费开源管理系统之一,但由于其广泛使用,也存在许多已知的安全漏洞。为了提高织梦CMS网站的安全性,以下是一些有效的安全防护设置步骤: 1. 修改网站后台的访问路径修改后台路径:默认后台路径为 http://域名/dede/。 修改为更复杂的路径,例如 http://…

静态QQ登录代码学习

记录学习 @搬砖界泰斗这只小狐狸 的静态QQ登陆页面源码,了解静态登陆页面如何书写&&拓宽自己对css的理解 Q1:用css调节子级元素位置时什么时候调节margin,什么时候调节padding? A1:margin对外,padding对内 e.g.要实现一个这样的排版 有一个大大盒子fafather,里面…

帝国CMS后台登陆时错误_enewsloginfail

当你在迁移帝国CMS网站后,遇到后台登录时出现“Table phome.***_enewsloginfail doesnt exist”的错误时,通常是因为数据库没有正确恢复。以下是详细的解决步骤: 1. 检查数据库恢复情况登录数据库管理工具:使用 phpMyAdmin 或其他数据库管理工具登录到数据库。检查数据库表…

解决 DedeCMS 报错“Please set ‘request_order’”的问题

如果你使用的是虚拟主机,无法直接修改 php.ini 文件,可以通过修改 DedeCMS 的代码来解决这个问题。找到 common.inc.php 文件:打开织梦CMS安装目录下的 include/common.inc.php 文件。修改代码:使用文本编辑器打开 common.inc.php 文件。找到第 34 行:phpif (strtoupper(i…

织梦错误Please set ‘request_order’

当你在使用 DedeCMS 并遇到错误提示“DedeCMS Error: (PHP 5.3 and above) Please set ‘request_order’ ini value to include C,G and P (recommended: ‘CGP’) in php.ini, more…”时,可以通过以下两种方法来解决这个问题: 方法 1:修改 php.ini 文件找到 php.ini 文件…

PbootCMS管理员密码忘记怎么办?pboot重置密码

1. PbootCMS 后台访问地址和初始密码后台访问地址:plaintexthttp://www.domain.com/admin.php将 www.domain.com 替换为你的实际域名。初始账号和密码:账号:admin 初始密码:1234562. 快速部署到本地或服务器 本地部署使用 PHPStudy:安装 PHPStudy 并按照官方文档搭建环境。…

织梦CMS后台登录验证码如何取消?

如果你想取消织梦CMS后台登录时的验证码,可以通过以下步骤进行操作: 1. 下载并编辑 inc_safe_config.php 文件下载文件:使用 FTP 客户端连接到服务器。 导航到网站根目录下的 DATA 文件夹。 找到 safe/inc_safe_config.php 文件并下载到本地。编辑文件:使用文本编辑器(如 …

执行SQL发生错误!错误:disk I/O error

当 PbootCMS 网站程序提示“执行 SQL 发生错误!错误:disk I/O error”时,通常是由于磁盘 I/O 错误导致的。这可能是由于磁盘空间不足或其他磁盘问题引起的。以下是一些详细的排查和解决步骤: 1. 检查磁盘空间登录服务器:使用 SSH 登录到服务器。检查磁盘空间:运行 df -h …