统计树上结点被访问次数:
走过u、v结点间的路径,则 sum[u]++,sum[v]++,sum[LCA(u,v)]--,sum[fa[LCA(u,v)]]--
int a[maxn], p[maxn][22];
int fa[maxn];
int dep[maxn];
int dif[maxn]; // 差分
int sum[maxn];
int n, m, k;
struct edge{
int v, next;
}e[maxn<<1];
int head[maxn], tot;
void add(int u, int v)
{
e[tot].v = v;
e[tot].next = head[u];
head[u] = tot++;
}
int LCA(int x, int y) { // 最近公共祖先
if (dep[x] > dep[y]) swap(x, y);
for (int i = 20; i >= 0; i--) {
if (dep[y] - (1 << i) >= dep[x])
y = p[y][i];
}
if (x == y) return x;
for (int i = 20; i >= 0; i--) {
if (p[x][i] == p[y][i]) continue;
x = p[x][i], y = p[y][i];
}
return p[x][0];
}
void dfs1(int x, int pre, int d)
{
dep[x] = d;
fa[x] = pre;
p[x][0] = pre;
for (int i = 1; (1 << i) <= dep[x]; i++)
p[x][i] = p[p[x][i - 1]][i - 1];
for(int i=head[x]; i!=-1;i = e[i].next)
{
if(e[i].v == pre)
continue;
dfs1(e[i].v, x, d+1);
}
}
void dfs2(int x, int pre)
{
// cout << x << endl;
for(int i=head[x];i!=-1;i=e[i].next)
{
int v = e[i].v;
// cout << "v:" << v << endl;
if(v==pre)
continue;
dfs2(v, x);
sum[x] += sum[v];
}
sum[x] += dif[x];
}
int main(){
// 建树...
for(int i=0;i<m;i++)
{
scanf("%d%d", &u, &v);
int zx = LCA(u, v);
dif[u]++; dif[v]++;
dif[zx]--;
dif[fa[zx]]--;
}
dfs2(1, 0);
}