倍增法求lca:暗的连锁
https://loj.ac/problem/10131
#include<bits/stdc++.h> using namespace std; struct node{ int to,next; }e[1000001]; int head[500000],num=0,N,n,m,ans; int grand[500001][20],depth[500001]; int f[100000],w[1000000]; inline void add(int x,int y) { e[++num].to=y,e[num].next=head[x],head[x]=num; } inline void read(int &x) { x=0;int f=1; char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} x*=f; } void dfs(int x) { for(int i=1;i<=N;i++)grand[x][i]=grand[grand[x][i-1]][i-1]; for(int i=head[x];i;i=e[i].next) { int v=e[i].to; if(v==grand[x][0])continue; depth[v]=depth[x]+1; grand[v][0]=x; dfs(v); } } void init() { N=floor(log(n+0.0)/log(2.0)); depth[1]=1; dfs(1); } inline int lca(int a,int b) { if(depth[a]>depth[b]) swap(a,b); for(register int i=N;i>=0;i--) { if(depth[a]<depth[b]&&depth[grand[b][i]]>=depth[a]) b=grand[b][i]; } if(a==b)return a; for(register int i=N;i>=0;i--) { if(grand[a][i]!=grand[b][i]){a=grand[a][i],b=grand[b][i];} } return grand[a][0]; } void solve(int u,int fa) { for(int i=head[u];i;i=e[i].next) { int v=e[i].to;if(v==fa) continue; solve(v,u);f[u]+=f[v]; } } int main() { read(n),read(m); for(int i=1;i<n;i++) { int u,v; read(u),read(v); add(u,v); add(v,u); } init(); for(int i=1;i<=m;i++) { int x,y; read(x),read(y); w[x]++;w[y]++; w[lca(x,y)]-=2; } for(int i=1;i<=n;i++) f[i]=w[i]; solve(1,0); for(int i=2;i<=n;i++) { if(f[i]==0) ans+=m; else if(f[i]==1) ans++; } cout<<ans; }