当前位置: 首页 > news >正文

CF29D Ant on the Tree

题目

CF29D Ant on the Tree
在这里插入图片描述

算法标签: d f s dfs dfs, 树上差分

思路

由于点的数量很少 300 300 300, 因此时间复杂度在 O ( n 3 ) O(n ^ 3) O(n3)之内都可以通过, 考虑 d f s dfs dfs, 从叶子结点开始搜, 因为 d f s dfs dfs记录顺序是逆序, 因此倒着搜就是正序, 时间复杂度 O ( n 2 ) O(n ^ 2) O(n2)

d f s dfs dfs代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>

using namespace std;

const int N = 310;

vector<int> head[N], ans;

void add(int u, int v) {
	head[u].push_back(v);
}

bool dfs(int u, int fa, int t) {
	if (u == t) return true;

	for (int v : head[u]) {
		if (v != fa && dfs(v, u, t)) {
			ans.push_back(v);
			return true;
		}
	}
	return false;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int n;
	cin >> n;
	for (int i = 0; i < n - 1; ++i) {
		int u, v;
		cin >> u >> v;
		add(u, v), add(v, u);
	}

	int t = 1, s;
	while (cin >> s) dfs(s, 0, t), t = s;
	dfs(1, 0, t);

	ans.push_back(1);
	if (ans.size() != 2 * n - 1) {
		cout << -1 << "\n";
		return 0;
	}

	for (int x : ans) cout << x << " ";
	cout << "\n";
	return 0;
}

树上差分代码

在差分过程中, 计算每个节点应该经过的次数, 然后在统计的时候就能计算出每个节点应该被经过多少次, 从而判断是否是合法的

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>

using namespace std;

const int N = 310, M = 10;

int n;
int fa[N][M], depth[N];
int diff[N], order[N], cnt;
vector<int> head[N];

void add(int u, int v) {
	head[u].push_back(v);
}

void dfs(int u, int pre, int dep) {
	fa[u][0] = pre, depth[u] = dep;
	int is_leaf = 1;
	for (int v : head[u]) {
		if (v == pre) continue;
		dfs(v, u, dep + 1);
		is_leaf = 0;
	}
	cnt += is_leaf;
}

int lca(int u, int v) {
	if (depth[u] < depth[v]) swap(u, v);
	for (int i = M - 1; i >= 0; --i) {
		if (depth[fa[u][i]] >= depth[v]) u = fa[u][i];
	}

	if (u == v) return u;

	for (int i = M - 1; i >= 0; --i) {
		if (fa[u][i] != fa[v][i]) {
			u = fa[u][i];
			v = fa[v][i];
		}
	}

	return fa[u][0];
}

void check(int u, int pre) {
	for (int v : head[u]) {
		if (v == pre) continue;
		check(v, u);
		diff[u] += diff[v];
	}
	if (u > 1 && diff[u] != 2) {
		cout << -1 << "\n";
		exit(0);
	}
}

void move(int u, int v) {
	int rev = 0;
	if (depth[u] < depth[v]) {
		swap(u, v);
		rev = 1;
	}

	vector<int> ans;
	while (u != v) {
		ans.push_back(rev ? u : fa[u][0]);
		u = fa[u][0];
	}

	if (rev) reverse(ans.begin(), ans.end());
	for (int u : ans) cout << u << " ";
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	cin >> n;
	for (int i = 0; i < n - 1; ++i) {
		int u, v;
		cin >> u >> v;
		add(u, v), add(v, u);
	}

	dfs(1, 0, 1);

	// 处理倍增数组
	for (int i = 1; i < M; ++i) {
		for (int u = 1; u <= n; ++u) {
			fa[u][i] = fa[fa[u][i - 1]][i - 1];
		}
	}

	// 起点终点都是1
	order[0] = order[cnt + 1] = 1;

	// 处理差分数组
	for (int i = 1; i <= cnt; ++i) {
		if (i <= cnt) cin >> order[i], diff[order[i]] += 2;
		int p = lca(order[i - 1], order[i]);
		diff[p] -= 2;
	}

	check(1, 0);

	cout << "1 ";
	for (int i = 1; i <= cnt + 1; ++i) {
		int p = lca(order[i - 1], order[i]);
		move(order[i - 1], p);
		move(p, order[i]);
	}
	cout << "\n";
	return 0;
}

相关文章:

  • openMP开发
  • 基于 Spring Boot 瑞吉外卖系统开发(四)
  • 博途 TIA Portal之1200做主站与汇川EASY的TCP通讯
  • 【第39节】windows编程:打造MFC版本任务管理器
  • C++11QT复习 (十九)
  • 大模型本地部署系列(2) Ollama部署DeepSeek-R1
  • Spring Security 的核心配置项详解,涵盖认证、授权、过滤器链、HTTP安全设置等关键配置,结合 Spring Boot 3.x 版本最佳实践
  • 数据校验和错误处理的方法与策略
  • Linux网络编程——TCP协议格式、可靠性分析
  • RHCSA Linux系统 vim 编辑器
  • Postman的内网使用教程
  • Python基础(一)
  • 重学Java基础篇—Java 反射机制及其用途
  • 记金仓数据库的一次优化
  • 中兴B860AV1.1-T2/B860AV2.2/B860AV2.2U-中星微ZX296716斜片芯片-刷机包及教程
  • 【rdma tx data flow问题】
  • Go语言比较递归和循环执行效率
  • 01背包 Java
  • 复现QGIS-MCP教程
  • 《从单体到分布式:一个订单系统的架构升级》
  • 网站建设资料/枣庄网站seo
  • 可视化网站建设软件/域名注册价格及续费
  • 模板工/深圳seo外包公司
  • 微信做淘宝客网站有哪些/域名关键词排名查询
  • 做网站买空间多少钱/百度关键词排名销售
  • 网站设计师/宁德市有几个区几个县