Max Flow P|P3128
https://www.luogu.com.cn/problem/P3128
裸的树上差分,不讲了。
//裸的树上差分吧
//「兴奋」
#include<iostream>
#include<cstring>
#define int long long
using namespace std;
//快读好习惯
inline int read(){
int s=0,f=1;
char c=getchar();
while(c<48 || c>57){if(c=='-')f=-f;c=getchar();}
while(c>=48 && c<=57)s=s*10+c-48,c=getchar();
return s*f;
}
const int MAXN=5e4+10;
const int MAXM=1e5+10;
int n,m;
//无根树
int tree[MAXN];
//树上差分就难蚌
//LCA啊啊啊
//不急慢慢来
//艹忘定义树了。。。
int head[MAXN];
struct tree{
int to;
int next;
}edge[MAXN*2];//双向!!!!!!
int _cnt=0;
void add(int u,int v){
edge[_cnt].to=v;
edge[_cnt].next=head[u];
head[u]=_cnt++;
}
int depth[MAXN];
int d[MAXN][20];//lca倍增用的
//定义1是根
void dfs(int x,int dep){
depth[x]=dep;
for(int i=head[x];i!=-1;i=edge[i].next){
int nxt=edge[i].to;
if(depth[nxt])continue;
d[nxt][0]=x;
for(int i=1;i<20;i++){
d[nxt][i]=d[d[nxt][i-1]][i-1];
}
dfs(nxt,dep+1);
}
return;
}
//LCA
int LCA(int u,int v){
if(depth[u]<depth[v]){//选最低的
swap(u,v);
}
for(int i=19;i>=0;i--){//跳到一起
if(depth[d[u][i]]>=depth[v])u=d[u][i];
}
if(u==v)return u;
for(int i=19;i>=0;i--){
if(d[u][i]!=d[v][i]){
u=d[u][i];
v=d[v][i];
}
}
return d[u][0];
}
//递归求解答案
bool vis[MAXN];
int dfs2(int x){
int ret=tree[x];
vis[x]=1;
for(int i=head[x];i!=-1;i=edge[i].next){
int nxt=edge[i].to;
if(vis[nxt])continue;
ret+=dfs2(nxt);
}
return tree[x]=ret;
}
signed main(){
memset(head,-1,sizeof(head));
n=read(),m=read();
int u,v;
for(int i=1;i<n;i++){
u=read(),v=read();
add(u,v);
add(v,u);
}
dfs(1,1);//深度也是1
for(int i=0;i<m;i++){
//打个LCAQQQQQQQQQQQQQQQ
u=read(),v=read();
int lca=LCA(u,v);
tree[u]++;
tree[v]++;
tree[lca]--;
tree[d[lca][0]]--;
}
dfs2(1);
int ans=0;
for(int i=1;i<=n;i++){
ans=max(ans,tree[i]);
}
cout<<ans;
return 0;
}