传送门

Luogu

解题思路

显然的贪心策略,因为每次都要尽量使得删点后的收益最大。

我们可以求出树的直径(因为树上的任意一个节点与其距离最远的点一定是直径的端点)。

然后我们对于所有不是直径上的点,从叶子开始,从下往上删点,最后再由深而浅删掉直径。

最后输出答案即可。

细节注意事项

  • 有些地方的计算不要写错式子之类的

参考代码

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <ctime>
#include <queue>
#define rg register
using namespace std;
template < typename T > inline void read(T& s) {
s = 0; int f = 0; char c = getchar();
while (!isdigit(c)) f |= (c == '-'), c = getchar();
while (isdigit(c)) s = s * 10 + (c ^ 48), c = getchar();
s = f ? -s : s;
} typedef long long LL;
const int _ = 200010;
const int __ = 400010; int tot, head[_], nxt[__], ver[__];
inline void Add_edge(int u, int v)
{ nxt[++tot] = head[u], head[u] = tot, ver[tot] = v; } int n, rt, lf, mark[_], fa[_], dep[_];
queue < pair < int, int > > Q; inline void dfs1(int u, int f) {
for (rg int i = head[u]; i; i = nxt[i]) {
int v = ver[i]; if (v == f) continue;
dep[v] = dep[u] + 1, dfs1(v, u);
}
} inline void dfs2(int u, int f) {
for (rg int i = head[u]; i; i = nxt[i]) {
int v = ver[i]; if (v == f) continue;
fa[v] = u, dfs2(v, u), mark[u] |= mark[v];
}
} LL ans = 0; inline void dfs3(int u, int f, int lca) {
for (rg int i = head[u]; i; i = nxt[i]) {
int v = ver[i]; if (v == f) continue;
dfs3(v, u, mark[v] ? v : lca);
}
if (!mark[u]) {
if (dep[u] > dep[u] + dep[lf] - 2 * dep[lca])
ans += dep[u], Q.push(make_pair(rt, u));
else
ans += dep[u] + dep[lf] - 2 * dep[lca], Q.push(make_pair(lf, u));
}
} int main() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
#endif
read(n);
for (rg int u, v, i = 1; i < n; ++i)
read(u), read(v), Add_edge(u, v), Add_edge(v, u);
dep[1] = 0, dfs1(1, 0);
rt = 1;
for (rg int i = 1; i <= n; ++i)
if (dep[i] > dep[rt]) rt = i;
dep[rt] = 0, dfs1(rt, 0);
lf = rt;
for (rg int i = 1; i <= n; ++i)
if (dep[i] > dep[lf]) lf = i;
mark[lf] = 1;
dfs2(rt, 0);
dfs3(rt, 0, rt);
for (rg int i = lf; i != rt; i = fa[i])
ans += dep[i], Q.push(make_pair(rt, i));
printf("%lld\n", ans);
while (!Q.empty()) {
pair < int, int > x = Q.front(); Q.pop();
printf("%d %d %d\n", x.first, x.second, x.second);
}
return 0;
}

完结撒花 \(qwq\)

最新文章

  1. [转]oracle job有定时执行的功能,可以在指定的时间点或每天的某个时间点自行执行任务。
  2. h5上传图片
  3. aspectj pointcut 找不到类型pointcut cannot be resolved to a type
  4. 获取验证码,60秒倒计时js
  5. LintCode &quot;Coins in a Line III&quot; !!
  6. Azkaban遇到的坑-installation Failed.Error chunking
  7. QT5中如何使用QFtp类(这个类虽然没有被收录,但一直在更新)
  8. [原创]Faster R-CNN论文翻译
  9. Java---Ajax在Struts2框架的应用实例
  10. Luogu P3372 【模板】线段树 1
  11. HTML5小游戏-简单抽奖小游戏
  12. (error) MOVED 5798 172.17.0.3:6379
  13. [ X.XX]CF每日一题系列线下更新中
  14. SliTaz 从入门到精通
  15. HDU 2066 一个人的旅行 (Dijkstra算法)
  16. 201709021工作日记--Volley源码详解(五)
  17. GTD实践2周年后一些体会
  18. JAVASCRIPT加密方法,JS加密解密综述(7种)
  19. 如何在HPUX的终端提示符前显示当前登录用户信息和所在目录
  20. Linux用户及权限分配

热门文章

  1. SpringMVC框架应用
  2. AcWing 874. 筛法求欧拉函数
  3. P1582 倒水(贪心 + lowbbit)
  4. AWS ec2的ubuntu14.04上安装git服务
  5. Scrapy爬取伯乐在线的所有文章
  6. 在MyEclipse2017中配置JDK和Tomcat8.5
  7. Panda的学习之路(1)——series 和 Dataframe
  8. Codeforces Round #618 (Div. 1)C(贪心)
  9. 学会C#可以做什么
  10. 《gPRC使用protobuf构建微服务》阅读笔记