There are m paths on the tree. bobo would like to pick some paths while any two paths do not share common vertices.
Find the maximum number of paths bobo can pick.
The first line contains n,m (1≤n,m≤105). Each of the following (n - 1) lines contain 2 integers ai,bi denoting an edge between vertices ai and bi (1≤ai,bi≤n). Each of the following m lines contain 2 integers ui,vi denoting a path between vertices ui and vi (1≤ui,vi≤n).
A single integer, the maximum number of paths.
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
const int INF=0x3f3f3f3f;
typedef long long LL;
const int maxn=101000;
const int maxq=101000;
int pre[maxn];
int d[maxn];
int find(int x)
{
if(pre[x]==-1) return x;
return pre[x]=find(pre[x]);
}
void Union(int a,int b)
{
a=find(a);b=find(b);
if(a!=b) pre[a]=b;
}
//****************
int vis[maxn],F[maxn];
int head[maxn],h[maxn];
int ans[maxq];
int tt,cnt;
struct node{
int to,next;
}e[maxn*2];
void addedge(int a,int b)
{
e[cnt].to=b;
e[cnt].next=head[a];
head[a]=cnt++;
}
//****************
struct Query{
int from,to,next;
int id;
}q[maxq*2],Q[maxq];
void add_query(int u,int v,int i)
{
q[tt].to=v;q[tt].next=h[u];
q[tt].id=i;h[u]=tt++;
q[tt].to=u;q[tt].next=h[v];
q[tt].id=i;h[v]=tt++;
}
//***************
void init()
{
tt=cnt=0;CLEAR(vis,false);
CLEAR(head,-1);CLEAR(h,-1);
CLEAR(F,0);CLEAR(ans,0);CLEAR(pre,-1);
}
int n,m;
void LCA(int u)
{
F[u]=u;vis[u]=true;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(vis[v]) continue;
d[v]=d[u]+1;
//cout<<"fuck "<<u<<" "<<v<<" "<<d[u]<<" "<<d[v]<<endl;
LCA(v);Union(u,v);
F[find(u)]=u;
}
for(int i=h[u];i!=-1;i=q[i].next)
{
int v=q[i].to;
if(vis[v])
ans[q[i].id]=F[find(v)];
}
}
int cmp(Query l1,Query l2)
{
int x=ans[l1.id];
int y=ans[l2.id];
return d[x]>d[y];
}
void dfs(int u)
{
vis[u]=true;
for(int i=head[u];i!=-1;i=e[i].next)
{
int to=e[i].to;
if(vis[to]||d[to]<d[u]) continue;
dfs(to);
}
}
int main()
{
int x,y;
while(~scanf("%d%d",&n,&m))
{
init();
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
addedge(x,y);
addedge(y,x);
}
for(int i=0;i<m;i++)
{
scanf("%d%d",&x,&y);
add_query(x,y,i);
Q[i].from=x;Q[i].to=y;
Q[i].id=i;
}
d[1]=0;
LCA(1);
sort(Q,Q+m,cmp);
CLEAR(vis,false);
int sum=0;
for(int i=0;i<m;i++)
{
if(!vis[Q[i].from]&&!vis[Q[i].to])
{
sum++;
dfs(ans[Q[i].id]);
}
}
printf("%d\n",sum);
}
return 0;
}