首页 > 其他分享 >Educational Codeforces Round 35 (Rated for Div. 2) F. Tree Destruction(树的直径/构造)

Educational Codeforces Round 35 (Rated for Div. 2) F. Tree Destruction(树的直径/构造)

时间:2022-11-14 17:13:13浏览次数:51  
标签:pre Educational Rated int Tree dep 直径 now root

题目大意是给定一棵树,每次选择两个叶子将其删除,同时将两个叶子之间的简单路径长度加到答案上,找到一种方案使答案最大化,并输出删除的顺序。

首先有一个结论是,距离树上某个节点最远的节点一定是某条直径的某个端点。

证明:反证法。设树上某条直径左端点为L,右端点为R,距离当前节点x最远的点为P。如果x就在直径上,那么P到L的简单路径/P到R的简单的路径长度中较大的那个值一定大于直径的长度,与直径定义矛盾。如果x不在直径上,那么设x到L的简单路径与直径重合的第一个点为Q,此时如果x到P的简单路径与直径不重合,因为x到P更远,所以用PL或者PR替代当前直径一定更优,与直径定义矛盾;如果x到P的简单路径与直径有重合,即x到P必定经过Q,因为xP>max(xL, xR),因此QP > max(QL, QR),同样可知用PL或者PR替代当前直径一定更优,与直径定义矛盾。

所以,最优的方案就是先从远到近删除不在直径上的点,然后删除直径。直径可用两次dfs求出。

#include <bits/stdc++.h>
#define int long long
#define en cout<<endl;
#define de(x) cout<<x;
#define N 200005
using namespace std;
int n, head[N], ver[2 * N], Next[2 * N], tot = 0;
void add(int x, int y) {
	ver[++tot] = y, Next[tot] = head[x], head[x] = tot;
}
int root, root2;
int mxdep = 0;
int dep[3][N];
int fa[N];
struct node {
	int a, b, c;
};
void dfs1(int x, int pre, int d) {
	if(d > mxdep) {
		mxdep = d;
		root = x;
	}
	for(int i = head[x]; i; i = Next[i]) {
		int y = ver[i];
		if(y == pre) continue;
		dfs1(y, x, d + 1);
	}
}
vector<node> v;
void dfs2(int x, int pre, int d, int round) {
	dep[round][x] = d;
	if(round == 1) {
		fa[x] = pre;
	}
	if(d > mxdep) {
		mxdep = d;
		root2 = x;
	}
	for(int i = head[x]; i; i = Next[i]) {
		int y = ver[i];
		if(y == pre) continue;
		dfs2(y, x, d + 1, round);
	}
}
bool link[N];
int ans = 0;
void dfs3(int x, int pre, vector<node> &v) {
	for(int i = head[x]; i; i = Next[i]) {
		int y = ver[i];
		if(y == pre) continue;
		dfs3(y, x, v);
	}
	if(link[x]) return;
	if(dep[1][x] > dep[2][x]) {
		ans += (dep[1][x] - 1);
		v.push_back({x, root, x});
	} else {
		ans += (dep[2][x] - 1);
		v.push_back({x, root2, x});
	}
}
void solve() {
	cin >> n;
	memset(dep, 0, sizeof(dep));
	memset(link, 0, sizeof(link));
	for(int i = 1; i < n; i++) {
		int u, v;
		cin >> u >> v;
		add(u, v);
		add(v, u);
	}
	dfs1(1, 0, 1);
	mxdep = 0;
	dfs2(root, 0, 1, 1);
	dfs2(root2, 0, 1, 2);
	int now = root2;
	vector<int> linkp;
	while(now) {
		link[now] = 1;
		ans += (dep[1][now] - 1);
		if(now != root) linkp.push_back(now);
		now = fa[now];
	}
	vector<node> v;
	dfs3(root, 0, v);
	for(auto x : linkp) {
		v.push_back({x, root, x});
	}
	cout << ans << endl;
	for(auto x : v) {
		cout << x.a << " " << x.b << " " << x.c << endl;
	}
	return;
}
signed main() {
	int T = 1;
	// cin >> T;
	while(T--) {
		solve();
	}
	return 0;
}

标签:pre,Educational,Rated,int,Tree,dep,直径,now,root
From: https://www.cnblogs.com/lipoicyclic/p/16889574.html

相关文章

  • [15-445]B+Tree memo
    B树是一个家族,感觉B+Tree对于喜欢使用MySQL的我来说是最常听说的数据库索引结构之一了。但是我从来没有从头到尾自己实现过一个B+Tree,像类似的数据结构,感觉不真正自......
  • TreeMap底层
    publicclassTreeMap<K,V>{//重要属性//外部比较器privatefinalComparator<?superK>comparator;//树的根节点privatetransientEntr......
  • vue2项目中使用 vue2-org-tree组件实现组织架构图
    1.安装及使用操作流程npm安装:npmivue2-org-tree安装loader,不然会报错npminstall--save-devlessless-loadermain.js文件引入并使用:importVue2OrgTreefrom'vue......
  • CodeForces - 1187E Tree Painting
    题意:给出一棵树,最开始所有节点都是白的。进行一些操作来计算树的价值。每次操作可以选一个节点,给价值加上包括这个结点在内的白色连通块大小。然后把这个结点染成黑色。除......
  • CodeForces - 1092F Tree with Maximum Cost
    题意:给出一棵树,每个结点有一个权值。定义一棵树以ai为根节点的价值为 剩下每个结点到根节点的距离乘权值 之和。求这棵树的最大价值。解:随便选一个结点为根,从下到上统......
  • TS 创建TreeNode类型
    想要实现的效果如:创建一个区域类,包含区域名称name,区域编码code,子区域childreninterfaceArea{name:string,code:string,children:Array<Area>}......
  • 运行npm install 时,卡在sill idealTree buildDeps没有反应
    .运行npminstall时,卡在sillidealTreebuildDeps没有反应npminstall一直停留在fetchMetadata:sillmapToRegistryurihttp://registry.npmjs.org/whatwg-fetch可以......
  • Codeforces Round #172 (Div. 1) C. Game on Tree(期望的线性性质)
    题意是给出一棵有根树,每次等概率删除一个点以及以其为根的子树,问删完整棵树的期望步数。暴力枚举方案显然不可,考虑期望的线性性质,将问题转化为删除每个点的期望步数再求和......
  • Educational Codeforces Round 109 (Rated for Div. 2) E. Assimilation IV(期望的线性
    题意是有n个城市和m个点,已知每个城市到每个点的距离为\(a_{ij}\),每秒进行一次操作,每次随机选一个没选过的城市建一个碑,其影响的范围每秒加一,求n秒后被影响的点数的期......
  • loj #10069. 「一本通 3.1 练习 4」Tree
    给你一个无向带权连通图,每条边是黑色或白色。求一棵最小权的恰好有K条白色边的生成树。题目保证有解  二分一个增加量md, 给每个白边权值加md,跑一下kruskal,......