首页 > 其他分享 >AtCoder Regular Contest 117 D Miracle Tree

AtCoder Regular Contest 117 D Miracle Tree

时间:2023-04-30 22:56:24浏览次数:50  
标签:AtCoder Contest int Tree dep edges maxn operatorname dis

洛谷传送门

AtCoder 传送门

第一步就没想到

可以考虑化简限制。设所有点按 \(E_i\) 从小到大排序后顺序是 \(p_1,p_2,...,p_n\)。发现只需满足 \(E_{p_{i+1}} - E_{p_i} \ge \operatorname{dis}(p_i, p_{i+1})\)。证明是对于任意 \(i < j < k\),若 \(p_i,p_j\) 和 \(p_j,p_k\) 均满足限制,那么 \(E_{p_k} - E_{p_i} = E_{p_k} - E_{p_j} + E_{p_j} - E_{p_i} \ge \operatorname{dis}(p_k, p_j) + \operatorname{dis}(p_j, p_i) \ge \operatorname{dis}(p_k, p_i)\)。

到这里显然每个不等式都可以取等,即 \(E_{p_{i+1}} = E_{p_i} + \operatorname{dis}(p_i, p_{i+1})\),\(E_{p_n} = 1 + \sum\limits_{i=1}^{n-1} \operatorname{dis}(p_i, p_{i+1})\)。则我们需要找到一个排列 \(p\),使得 \(\sum\limits_{i=1}^{n-1} \operatorname{dis}(p_i, p_{i+1})\) 最小。

注意到 \(\sum\limits_{i=1}^{n-1} \operatorname{dis}(p_i, p_{i+1}) + \operatorname{dis}(p_n, p_1)\) 最小值为 \(2(n-1)\),这是因为每条边至少经过两次。取到下界也很简单,\(p\) 取 dfs 序即可。

现在就变成了要最大化 \(\operatorname{dis}(p_1, p_n)\)。\(p_1,p_n\) 取直径端点即可。

code
// Problem: D - Miracle Tree
// Contest: AtCoder - AtCoder Regular Contest 117
// URL: https://atcoder.jp/contests/arc117/tasks/arc117_d
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 200100;

int n, head[maxn], len, s, t;
int point, maxd, p[maxn], f[maxn], tot, a[maxn];
int fa[maxn], dep[maxn], son[maxn], sz[maxn];
int top[maxn];
bool vis[maxn];

struct edge {
	int to, next;
} edges[maxn << 1];

inline void add_edge(int u, int v) {
	edges[++len].to = v;
	edges[len].next = head[u];
	head[u] = len;
}

void dfs(int u, int fa, int d) {
	if (d > maxd) {
		maxd = d;
		point = u;
	}
	for (int i = head[u]; i; i = edges[i].next) {
		int v = edges[i].to;
		if (v == fa) {
			continue;
		}
		dfs(v, u, d + 1);
	}
}

void dfs2(int u, int fa) {
	if (u == t) {
		f[u] = 1;
	}
	for (int i = head[u]; i; i = edges[i].next) {
		int v = edges[i].to;
		if (v == fa) {
			continue;
		}
		dfs2(v, u);
		f[u] |= f[v];
	}
}

void dfs3(int u, int fa) {
	p[++tot] = u;
	int x = -1;
	for (int i = head[u]; i; i = edges[i].next) {
		int v = edges[i].to;
		if (v == fa) {
			continue;
		}
		if (f[v]) {
			x = v;
			continue;
		}
		dfs3(v, u);
	}
	if (x != -1) {
		dfs3(x, u);
	}
}

int dfs4(int u, int f, int d) {
	fa[u] = f;
	sz[u] = 1;
	dep[u] = d;
	int maxson = -1;
	for (int i = head[u]; i; i = edges[i].next) {
		int v = edges[i].to;
		if (v == f) {
			continue;
		}
		sz[u] += dfs4(v, u, d + 1);
		if (sz[v] > maxson) {
			son[u] = v;
			maxson = sz[v];
		}
	}
	return sz[u];
}

void dfs5(int u, int tp) {
	top[u] = tp;
	vis[u] = 1;
	if (!son[u]) {
		return;
	}
	dfs5(son[u], tp);
	for (int i = head[u]; i; i = edges[i].next) {
		int v = edges[i].to;
		if (!vis[v]) {
			dfs5(v, v);
		}
	}
}

inline int qlca(int x, int y) {
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]]) {
			swap(x, y);
		}
		x = fa[top[x]];
	}
	if (dep[x] > dep[y]) {
		swap(x, y);
	}
	return x;
}

inline int qdis(int x, int y) {
	return dep[x] + dep[y] - dep[qlca(x, y)] * 2;
}

void solve() {
	scanf("%d", &n);
	for (int i = 1, u, v; i < n; ++i) {
		scanf("%d%d", &u, &v);
		add_edge(u, v);
		add_edge(v, u);
	}
	dfs(1, -1, 1);
	maxd = 0;
	s = point;
	dfs(s, -1, 1);
	t = point;
	dfs2(s, -1);
	dfs3(s, -1);
	dfs4(s, -1, 1);
	dfs5(s, s);
	a[p[1]] = 1;
	for (int i = 2; i <= n; ++i) {
		a[p[i]] = a[p[i - 1]] + qdis(p[i - 1], p[i]);
	}
	for (int i = 1; i <= n; ++i) {
		printf("%d ", a[i]);
	}
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:AtCoder,Contest,int,Tree,dep,edges,maxn,operatorname,dis
From: https://www.cnblogs.com/zltzlt-blog/p/17365911.html

相关文章

  • AtCoder Beginner Contest 231
    A-WaterPressure#include<bits/stdc++.h>usingnamespacestd;intmain(){ intn; cin>>n; printf("%.6lf\n",n/100.0);return0;}B-Election#include<bits/stdc++.h>usingnamespacestd;intmain(){ ios:......
  • Educational DP Contest
    EducationalDPContestATcoder_link夯实基础的好东西I记录一下此时第i个有多少概率小于等于j的就可以了。#include<bits/stdc++.h>usingnamespacestd;constintN=3005;#definedbdoubledbdp[N][N];intn;dbp[N];intmain(){ios::sync_with_stdio(fal......
  • AtCoder比赛记录(一)
    这里记录的是这个账号的比赛情况。ARC1572023-2-25Solved:4/62189->2216C(Medium,1802)给定一个XY矩阵,一条左上角到右下角的路径的分值定义为路径上连续两个Y的组数。求所有可能路径的分值的平方和。Solution:经典DP。递推两个量,一个是到(i,j)所有路径的分值和\(f_{i,j}\),......
  • AtCoder比赛记录(二)
    这里记录的是这个账号的比赛情况。ABC3002023-4-29Solved:7/80->1200F(Medium-,1846)给定由o和x组成的字符串\(S\)。将\(S\)复制\(m\)遍,然后将其中\(k\)个x改成o,求改完之后连续的o最多可能有多少个。Solution:贪心。设最多能改完\(t\)个完整的\(S\),考虑三类情况:最长连续......
  • Codeforces 1799H - Tree Cutting(树形 dp)
    思考的时候一直卡在不会在低于\(O(n)\)的时间内储存一个连通块的\(siz\)有关的信息,看了洛谷题解之后才发现我真是个小丑。树形DP。对于一条我们需要操作的边\((i,fa_i)\),我们将其分为保留子树和删除子树两种类型,对于删除子树,我们在判定其是否合法时候改为判定删除的连通块......
  • AtCoder Regular Contest 116 F Deque Game
    洛谷传送门AtCoder传送门很强的博弈+性质题。下文令A为Takahashi,B为Aoki。发现单独考虑一个序列\(a_1,a_2,...,a_n\):若\(n\bmod2=0\):若A为先手,答案为\(\max(a_{\frac{n}{2}},a_{\frac{n}{2}+1})\);若B为先手,答案为\(\min(a_{\frac{n}{2}},a_{\frac......
  • 二叉树Binary Tree
    二叉树BinaryTree1.树的一些常用术语2.二叉树的概念树有很多种,每个节点最多只能有两个子节点的一种形式称为二叉树;二叉树的子节点分为左子节点和右子节点;以下三种均为二叉树:若该二叉树的所有叶子节点都在最后一层,且节点总数n==\(2^k\)-1,k为层数,则称为满二叉树......
  • 现在告诉你MySQL为什么选择B+Tree呢?
    大家都知道MySQL数据库选择的是B+Tree作为索引的数据结构,那为什么会选择B+Tree呢?本文分四种数据结构来分析:二叉查找树平衡二叉树多路平衡查找树加强版多路平衡查找树(B+Tree)二叉查找树二叉搜索树的特点:左子树的键值小于根的键值,右子树的键值大于根的键值。   从上面的2个图来看......
  • AtCoder Regular Contest 123 E Training
    洛谷传送门AtCoder传送门不妨假设\(B_X\leB_Y\)。设\(f(x)=A_X+\frac{x}{B_X},g(x)=A_Y+\frac{x}{B_Y},F(x)=\left\lfloor{f(x)}\right\rfloor,G(x)=\left\lfloor{g(x)}\right\rfloor\),题目即求\(\sum\limits_{x=1}^n[F(x)=G(x)]\)。我一开始尝试化简......
  • el-tree实现树形结构叶子节点和非叶子节点的区分显示的写法
    需求,非叶子节点显示主题名称+主题下的指标;叶子节点显示代码+名称1、设置prop属性<el-tree:data="dimListTree"ref="dimListTree"row-key="getGroup":props="treeProps":allow-drop="al......