思路
LCA+差分
如果u和v之间有一条路径,那这条路径就是u->lca(u,v)->v的,这一串上的结点都需要加一,也就是c[u]++;c[v]++;c[lca(u,v)]--;c[fa[lca(u,v)]]--;
LCA倍增比较方便,最后在跑一遍前缀和
Code
#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;
#define int long long
#define F(i,a,b) for(int i=(a);i<=(b);i++)
const int N=5e5+5;
vector<int> G[N];
int n,m,ans=0,x,y;
int f[N][100];
int dep[N];
int Log[N];
int c[N],sum[N];
int lowbit(int x)
{
return x&(-x);
}
//初始化
void dfs(int rt,int fa)
{
f[rt][0]=fa;
dep[rt]=dep[fa]+1;
F(i,0,G[rt].size()-1)
{
int v=G[rt][i];
if(v==fa) continue;
dfs(v,rt);
}
}
//算前缀和
void dfs1(int rt,int fa)
{
F(i,0,G[rt].size()-1)
{
int v=G[rt][i];
if(v==fa) continue;
dfs1(v,rt);
c[rt]+=c[v];
}
}
//树上倍增求LCA
int lca(int a,int b)
{
if(dep[a]<dep[b]) swap(a,b);
for(int i=dep[a]-dep[b];i;i-=lowbit(i))
{
int j=Log[lowbit(i)];
a=f[a][j];
}
if(a==b) return a;
for(int i=Log[n];i>=0;i--)
{
if(f[a][i]!=f[b][i])
{
a=f[a][i];
b=f[b][i];
}
}
return f[a][0];
}
signed main()
{
cin>>n>>m;
F(i,1,n-1)
{
cin>>x>>y;
G[x].push_back(y);
G[y].push_back(x);
}
dfs(1,0);
F(i,2,n) Log[i]=Log[i/2]+1;
for(int j=1;j<=Log[n];j++)
{
F(i,1,n)
{
f[i][j]=f[f[i][j-1]][j-1];
}
}
F(i,1,m)
{
cin>>x>>y;
int t=lca(x,y);
//差分
c[x]++;
c[y]++;
c[t]--;
c[f[t][0]]--;
}
dfs1(1,0);
int maxx=0;
for(int i=1;i<=n;i++) maxx=max(maxx,c[i]);
cout<<maxx;
return 0;
}