dfs序 & 歐拉序

dfs序:
s[u]: dfs時進入u節點子樹時的時間戳;
s[v]: dfs時離開u節點子樹時的時間戳.
歐拉序:
E[i]: 第i時間訪問到的節點

R[u]: 節點u被訪問到的第一時間

Question:

給定樹形圖,然後q次詢問,問點u是否是點v的父節點。

Answer:

通過dfs序判斷v節點的時間區間是否在u節點的時間區間內。

通過歐拉序判斷u和v的最近公共祖先是否是u。

Code1:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
vector<int> g[maxn];
int s[maxn], e[maxn];
int n, q, id;
void dfs(int u, int fa) {
	s[u] = ++id;
	for(int i = 0; i < g[u].size(); ++i) {
		int v = g[u][i];
		if(v == fa) continue;
		dfs(v, u);
	}
	e[u] = id;
}
int main() {
	ios::sync_with_stdio(0);
	cin >> n >> q;
	for(int i = 1; i < n; ++i) {
		int u, v;
		cin >> u >> v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	id = 0;
	dfs(1, -1);
	for(int i = 1; i <= q; ++i) {
		int u, v;
		cin >> u >> v;
		if(s[u] <= s[v] && e[v] <= e[u]) {
			cout << "YES" << endl;
		}
		else {
			cout << "NO" << endl;
		}
	}
	return 0;
}

Code2:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
vector<int> g[maxn];
int E[maxn*2], R[maxn], dep[maxn];
int f[maxn*2][20];
int n, q, cnt;
void dfs(int u, int fa, int deps) {
	E[++cnt] = u;
	R[u] = cnt;
	dep[u] = deps;
	for(int i = 0; i < g[u].size(); ++i) {
		int v = g[u][i];
		if(v == fa) continue;
		dfs(v, u, deps+1);
		E[++cnt] = u;
	}
}
void rmq_init() {
	for(int i = 1; i <= cnt; ++i) {
		f[i][0] = E[i];
	}
	for(int j = 1; (1<<j) <= cnt; ++j) {
		for(int i = 1; i+(1<<j)-1 <= cnt; ++i) {
			int u = f[i][j-1], v = f[i+(1<<(j-1))][j-1];
			f[i][j] = dep[u] < dep[v] ? u : v;
		}
	}
}
int rmq(int i, int j) {
	int k = log2(j-i+1);
	int u = f[i][k], v = f[j-(1<<k)+1][k];
	return dep[u] < dep[v] ? u : v;
}
int lca(int u, int v) {
	return rmq(min(R[u], R[v]), max(R[u], R[v]));
}
int main() {
	ios::sync_with_stdio(0);
	cin >> n >> q;
	for(int i = 1; i < n; ++i) {
		int u, v;
		cin >> u >> v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	cnt = 0;
	dfs(1, -1, 1);
	rmq_init();
	for(int i = 1; i <= q; ++i) {
		int u, v;
		cin >> u >> v;
		if(lca(u, v) == u) {
			cout << "YES" << endl;
		}
		else {
			cout << "NO" << endl;
		}
	}
	return 0;
}

加油~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章