传送门:点击打开链接
题意:一棵树,告诉你两个点,求两个点之间的距离
思路:裸LCA。维护点到根节点的距离,那么u到根节点距离+v到根节点距离-lca(u,v)到根节点距离即可
离线LCA的思路很清晰,大概就是利用从下向上的并查集去维护节点。
#include<map> #include<set> #include<cmath> #include<stack> #include<queue> #include<cstdio> #include<cctype> #include<string> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #include<functional> #define fuck printf("fuck") #define FIN freopen("input.txt","r",stdin) #define FOUT freopen("output.txt","w+",stdout) using namespace std; typedef long long LL; const int MQ = 40000 + 5; const int MX = 80000 + 5; struct Edge { int v, d; Edge(int _v, int _d) { v = _v; d = _d; } }; struct Que { int id, u, v; Que() {} Que(int _u, int _v, int _id) { u = _u; v = _v; id = _id; } } A[MQ]; int D[MX]; struct LCA { int n, ans[MQ]; int P[MX]; bool vis[MX]; vector<Edge>E[MX]; vector<Que>Q[MQ]; void Init(int _n) { n = _n; memset(ans, -1, sizeof(ans)); memset(vis, false, sizeof(vis)); for(int i = 1; i <= n; i++) { E[i].clear(); Q[i].clear(); P[i] = i; } } void AddQue(int u, int v, int id) { Q[u].push_back(Que(u, v, id)); Q[v].push_back(Que(v, u, id)); } void AddEdge(int u, int v, int d) { E[u].push_back(Edge(v, d)); E[v].push_back(Edge(u, d)); } int Find(int x) { return P[x] == x ? x : (P[x] = Find(P[x])); } void Union(int u, int v) { int p1 = Find(u), p2 = Find(v); P[p1] = p2; } void DFS(int u, int f, int d) { D[u] = d; for(int i = 0; i < E[u].size(); i++) { int v = E[u][i].v, cost = E[u][i].d; if(v != f) DFS(v, u, d + cost); } vis[u] = 1; for(int i = 0; i < Q[u].size(); i++) { int v = Q[u][i].v, id = Q[u][i].id; if(vis[v]) { ans[id] = Find(v); } } Union(u, f); } } lca; int main() { int T, n, m; //FIN; scanf("%d", &T); while(T--) { scanf("%d%d", &n, &m); lca.Init(n); int u, v, d; for(int i = 1; i <= n - 1; i++) { scanf("%d%d%d", &u, &v, &d); lca.AddEdge(u, v, d); } for(int i = 1; i <= m; i++) { scanf("%d%d", &u, &v); lca.AddQue(u, v, i); A[i] = Que(u, v, i); } lca.DFS(1, 1, 0); for(int i = 1; i <= m; i++) { int u = A[i].u, v = A[i].v, f = lca.ans[i]; printf("%d\n", D[u] + D[v] - 2 * D[f]); } } return 0; }