题源:https://loj.ac/problem/10130
这个题还是debug了好久。。
1.调用函数中如果要更改外部数据需要传递引用,其实传递引用往往效率更高,以后要多加注意这一点。
2.忘写并查集了(捂脸逃)
3.题目要求的是距离而不是lca,认真审题。。
贴代码:
#include <iostream> #include <stdio.h> #include <cstring> #define maxn 100005 //#define LOCAL using namespace std; struct Edge { int next, to, dis; } edge[maxn * 2], queryEdge[maxn * 2]; //两倍存储(不知道父子关系与遍历的先后顺序) int head[maxn], queryHead[maxn], e1 = -1, e2 = -1, fa[maxn], vs[maxn], dep[maxn]; //dep用来记录深度求距离 void addedge(int *head, Edge *edge, int &e, int x, int y) //e要传递引用来进行更改,否则++无效 { edge[++e].next = head[x], edge[e].to = y, head[x] = e; edge[++e].next = head[y], edge[e].to = x, head[y] = e; } int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); } //居然忘写了。。 void tarjan(int u, int pre) //要多传入一个前置节点参数以更改dep,自上往下更新 { vs[u] = 1; dep[u] = dep[pre] + 1; #ifdef LOCAL cout << u << " : " << dep[u] << endl; #endif int v; for (int i = head[u]; ~i; i = edge[i].next) // ~i等同于i != -1 { v = edge[i].to; if (!vs[v]) { tarjan(v, u); fa[v] = u; //更改dep不能放在这,这是自下往上更新 } } for (int i = queryHead[u]; ~i; i = queryEdge[i].next) { v = queryEdge[i].to; if (vs[v]) { queryEdge[i].dis = queryEdge[i ^ 1].dis = dep[u] + dep[v] - 2 * dep[find(v)]; } } } int main() { #ifdef LOCAL freopen("out.txt", "w", stdout); #endif memset(head, 0xff, sizeof(head)); //oxff全部初始化为-1 memset(queryHead, 0xff, sizeof(queryHead)); memset(vs, 0, sizeof(vs)); int n, q, x, y; scanf("%d", &n); for (int i = 1; i <= n - 1; ++i) { fa[i] = i; //不要忘了初始化father数组 scanf("%d%d", &x, &y); addedge(head, edge, e1, x, y); } fa[n] = n; scanf("%d", &q); for (int i = 1; i <= q; ++i) { scanf("%d%d", &x, &y); addedge(queryHead, queryEdge, e2, x, y); } #ifdef LOCAL // for (int i = 0; i <= e1; ++i) cout << i << " -> " << edge[i].to << endl; #endif dep[0] = 0; tarjan(1, 0); //根节点传入辅助0 #ifdef LOCAL for (int i = 1; i <= n; ++i) cout << i << "->" << fa[i] << endl; #endif for (int i = 0; i < e2; i += 2) { printf("%d\n", queryEdge[i].dis); } }
来源:https://www.cnblogs.com/jionkitten/p/12213681.html