1. 程式人生 > 其它 >思維訓練——CF1304E 1-Trees and Queries

思維訓練——CF1304E 1-Trees and Queries

題目連結:https://www.luogu.com.cn/problem/CF1304E

這道題稍微想了一下就有思路了。

讓我們先來簡化一下問題,如果沒有加邊,僅僅是詢問的話,那麼該怎麼做呢。

很明顯在兩點樹上的路徑只有一條,那麼我們很容易求出u和v的距離dis(u, v)又因為可以來回走,所以就是問dis(u, v) + 2x 是否能 == k

那麼這個問題其實就是問dis(u, v) - k 能否被2整除

現在我們考慮加邊的情況。加上了一條邊其實有三種情況(我想的不是很周到漏掉了第三種

1. 不通過加邊 求dis(u, v) + 2x 是否能 == k

2. 通過加邊 求dis(u, x) + dis(y, v) + 2x 是否能 == k

3. 通過加邊 求dis(u, y) + dis(x, v) + 2x 是否能 == k

同時注意不要大於k就行

需要會LCA基礎知識(這裡用得是倍增LCA

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e6 + 10;

int n, m;
vector<int> G[maxn];
int dep[maxn], lg[maxn];
int f[maxn][32];

void BFS(int x) {
    queue<int> q; q.push(x);
    dep[x] 
= 1; while (q.size()) { int u = q.front(); q.pop(); for (auto v : G[u]) { if (dep[v]) continue; dep[v] = dep[u] + 1; f[v][0] = u; q.push(v); for (int j = 1; j <= lg[dep[v]]; ++ j) { f[v][j] = f[f[v][j-1]][j-1]; } } } }
int LCA(int u, int v) { if (dep[u] < dep[v]) swap(u, v); ///根據差距倍增上跳 while (dep[u] > dep[v]) u = f[u][ lg[dep[u] - dep[v]] - 1]; if (u == v) return u; for (int i = lg[dep[u]] - 1; i >= 0; -- i) { if (f[u][i] != f[v][i]) u = f[u][i], v = f[v][i]; } return f[u][0]; } void init() { for (int i = 1; i <= n; ++ i) lg[i] = lg[i-1] + (1 << lg[i-1] == i); } int query(int u, int v) { int _lca = LCA(u, v); //cout << _lca << endl; return dep[u] + dep[v] - 2 * dep[_lca]; } int main() { scanf("%d", &n); for (int i = 1; i <= n-1; ++ i) { int u, v; scanf("%d%d", &u, &v); G[u].push_back(v); G[v].push_back(u); } init(); BFS(1); scanf("%d", &m); while (m--) { int x, y, u, v, k; scanf("%d%d%d%d%d", &x, &y, &u, &v, &k); int flag = 0; ///u - v int ans1 = query(u, v); if (ans1 <= k && (k - ans1) % 2 == 0) { flag = 1; } ///u - x - y - v int ans2 = query(u, x) + query(y, v) + 1; if (ans2 <= k && (k - ans2) % 2 == 0) { flag = 1; } ///u - y - x - v int ans3 = query(u, y) + query(x, v) + 1; if (ans3 <= k && (k - ans3) % 2 == 0) { flag = 1; } //cout << ans1 << " " << ans2 << " " << ans3 << endl; if (flag) puts("YES"); else puts("NO"); } return 0; }