標籤:blog os io strong for ar div line
這道題的題意其實有點略晦澀,定義f(a,b)為 minimum of vertices not on the path between vertices a and b. 其實它加一個minimum index of vertices應該會好理解一點吧。看了一下題解,還有程式,才理清思路。
首先比較直接的是如果兩點的路徑沒有經過根節點1的話,那麼答案就直接是1,否則的話就必然有從根節點出發的兩條路徑,題解裡說的預先處理出f[u]表示不在根節點到u的路徑上的點的最小值,然後取f[u]和f[v]的最小值看了我半天。因為如果是這樣的話,那麼下面這個圖不就可以輕易cha掉這種做法?
1->2 1->3 2->4 4->6 4->7 3->5 5->8 5->9
詢問(6,8)的時候顯然f(6)是3,f(8)是2,那麼輸出的答案就會是2,但實際上應該輸出的是7。
後來仔細探究了才發現,f[u]存的只是 從不在根節點到u的路徑的最小值(其中不包括根節點到別的子節點的路徑),換言之上面的f[6]裡只存了7,f[8]裡只存了9,所以min(7,9)=7。
但是這個時候我們可能就會出錯了,因為如果根節點如果連出去有第三條路徑的話,那麼這條路徑的最小值我們是沒有包含到的,所以對於根節點我們要存它最小值的子樹,還有也要存對於每個節點它來自於哪個子樹。
剩下的就是一個類似樹dp的過程了。
然後題目還溫馨提示了可能會逾時,可能要寫個輸入掛什麼的,所以寫鄰接表的可能都不能寫vector的形式了吧。
#pragma warning(disable:4996)#include <iostream>#include <cstring>#include <string>#include <vector>#include <cstdio>#include <cmath>#include <algorithm>using namespace std;#define maxn 1005000#define inf 0x3f3f3f3fint child[maxn][4];int subtree[maxn];int path[maxn];int fa[maxn];int bel[maxn];int que[maxn];int qh, qt;int n, nQ;int head[maxn];int nxt[maxn<<1];int vv[maxn<<1];int tot;void add_Edge(int u,int v){vv[tot] = v; nxt[tot] = head[u]; head[u] = tot++;}void bfs(){qh = qt = 0;que[qt++] = 1; fa[1] = -1;while (qh < qt){int u = que[qh++];for (int i = head[u]; ~i; i=nxt[i]){int v = vv[i];if (v == fa[u]) continue;fa[v] = u;que[qt++] = v;}}for (int i = 0; i <= n; ++i){for (int j = 0; j < 4; ++j){child[i][j] = inf;}}for (int i = n - 1; i >= 0; --i){int u = que[i]; subtree[u] = u;for (int j = head[u]; ~j; j=nxt[j]){int v = vv[j];if (v == fa[u]) continue;child[u][3] = subtree[v];sort(child[u], child[u] + 4);}subtree[u] = min(subtree[u], child[u][0]);}qh = qt = 0;for (int i = head[1]; ~i; i=nxt[i]){int v = vv[i];que[qt++] = v;bel[v] = subtree[v];path[v] = inf;}while (qh < qt){int u = que[qh++];for (int i = head[u]; ~i; i=nxt[i]){int v = vv[i];if (v == fa[u]) continue;bel[v] = bel[u];if (subtree[v] == child[u][0]){path[v] = min(path[u], child[u][1]);}else{path[v] = min(path[u], child[u][0]);}que[qt++] = v;}path[u] = min(path[u], child[u][0]);}}int query(int qu, int qv){if (qu > qv) swap(qu, qv);if (qu != 1 && bel[qu] == bel[qv]) return 1;int i = 0;while (child[1][i] == bel[qu] || child[1][i] == bel[qv]){i++;}int ret = qu == 1 ? path[qv] : min(path[qu], path[qv]);ret = min(ret, child[1][i]);return ret;}inline void scan(int &n){char cc;for (; cc = getchar(), cc<‘0‘ || cc>‘9‘;);n = cc - ‘0‘;for (; cc = getchar(), cc >= ‘0‘&&cc <= ‘9‘;)n = n * 10 + cc - ‘0‘;}int main(){while (cin >> n >> nQ){tot = 0; memset(head, -1, sizeof(head));int ui, vi;for (int i = 0; i < n - 1; ++i){//scan(ui); scan(vi);scanf("%d%d", &ui, &vi);add_Edge(ui, vi);add_Edge(vi, ui);}bfs();int last = 0;for (int i = 0; i < nQ; ++i){//scan(ui); scan(vi);scanf("%d%d", &ui, &vi);ui ^= last; vi ^= last;printf("%d\n", last=query(ui, vi));}}return 0;}