1. 程式人生 > >L - Subway Lines Gym - 101908L [LCA+思維]

L - Subway Lines Gym - 101908L [LCA+思維]

題意:給出一棵樹,然後給出兩個數對 ( a , b ) (a, b) , ( c

, d ) (c, d) ,詢問在ab的最短路和cd的最短路重合了幾個點。


題解:才開始想要標記路徑但是LCA是倍增的不好弄,時間複雜度也太高,然後想了一下樹上求最短路的知識,然後想到他們的LCA的高度,然後通過交叉走判斷是否有重合的點。具體先選擇LCA較小的點作為比較物件,然後另外兩個點向當前兩個點求LCA看高度與最低的LCA路徑和,最後別忘了加上1(祖先)


a c c o d e : ac code:

#include
<bits/stdc++.h>
using namespace std; typedef long long ll; #define met(a, b) memset(a, b, sizeof(a)) #define rep(i, a, b) for(int i = a; i <= b; i++) #define per(i, a, b) for(int i = a; i >= b; i--) #define debug cout << "*" << endl; const int maxn = 1e5 + 10; const int inf = 0x3f3f3f3f; const int DEG = 20; struct Edge { int to, next; } edge[maxn << 1]; int head[maxn], tot; void addEdge(int u, int v) { edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; } void init() { tot = 0; met(head, -1); } int fa[maxn][DEG], deg[maxn]; void BFS(int root) { queue<int> que; deg[root] = 0; fa[root][0] = root; que.push(root); while(!que.empty()) { int tmp = que.front(); que.pop(); for(int i = 1; i < DEG; i++) fa[tmp][i] = fa[fa[tmp][i - 1]][i - 1]; for(int i = head[tmp]; i != -1; i = edge[i].next) { int v = edge[i].to; //cout << v << endl; if(v == fa[tmp][0]) continue; deg[v] = deg[tmp] + 1; fa[v][0] = tmp; que.push(v); } } } int LCA(int u, int v) { if(deg[u] > deg[v]) swap(u, v); int hu = deg[u], hv = deg[v]; int tu = u, tv = v; for(int det = hv - hu, i = 0; det; det >>= 1, i++) { if(det & 1) tv = fa[tv][i]; } if(tu == tv) return tu; for(int i = DEG - 1; i >= 0; i--) { if(fa[tu][i] == fa[tv][i]) { continue; } tu = fa[tu][i]; tv = fa[tv][i]; } return fa[tu][0]; } bool flag[maxn]; int N, Q; int dis(int a, int b) { int f = LCA(a, b); return deg[a] + deg[b] - 2 * deg[f]; } int solve(int a, int b, int c, int d) { int lca = LCA(c, d); int t = LCA(a, b); if(deg[lca] < deg[t]) { lca = t; swap(a, c); swap(b, d); } t = LCA(a, c); int res = 0; int f = 0; if(deg[t] > deg[lca]) { res += dis(t, lca); } else if(deg[t] == deg[lca]) { f = 1; } t = LCA(a, d); if(deg[t] > deg[lca]) { res += dis(t, lca); } else if(deg[t] == deg[lca]) { f = 1; } t = LCA(b, c); if(deg[t] > deg[lca]) { res += dis(t, lca); } else if(deg[t] == deg[lca]) { f = 1; } t = LCA(b, d); if(deg[t] > deg[lca]) { res += dis(t, lca); } else if(deg[t] == deg[lca]) { f = 1; } res += f; return res; } int main() { int u, v, a, b, c, d; while(~scanf("%d%d", &N, &Q)) { init(); met(flag, false); rep(i, 2, N) scanf("%d%d", &u, &v), addEdge(u, v), addEdge(v, u), flag[v] = true; int root; for(int i = 1; i <= N; i++) { if(!flag[i]) { root = i; break; } } BFS(root); while(Q--) { scanf("%d%d%d%d", &a, &b, &c, &d); printf("%d\n", solve(a, b, c, d)); } } return 0; }