题意:给出一些树边组成一棵树,再给出一些路径,然后问在选择得点不能重叠得情况下 最多能够选择多少路径
解法:贪心得思想是在对于所有路径上两点得lca深度排序 优先选择深度比较小的 然后标记该路径不能选择
则可以选择出最多的路径 具体实现的时候要用并查集维护一下 如果没有找到就连到父节点上 如果找到了就把lca除外
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
#define maxn 111111
#define D 20
int n,m,a[maxn],b[maxn],depth[maxn],pa[D][maxn],f[maxn];
vector<int>e[maxn],qu[maxn];
int lca(int a,int b){
if(depth[a]>depth[b])swap(a,b);
for(int i=D-1;i>=0;i--){
if((depth[b]-depth[a])>>i&1){
b=pa[i][b];
}
}
if(a==b)return a;
for(int i=D-1;i>=0;--i){
if(pa[i][a]!=pa[i][b]){
a=pa[i][a];b=pa[i][b];
}
}
return pa[0][a];
}
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
int main()
{
while(~scanf("%d%d",&n,&m)){
fill(e,e+n,vector<int>());//清空边
for(int i=0;i<n-1;++i){
int a,b;scanf("%d%d",&a,&b);--a;--b;
e[a].push_back(b);e[b].push_back(a);
}
//calculator depth && init pa[0][]
vector<int>queue;
{
int* parent=pa[0];
depth[0]=0;
parent[0]=-1;
queue.push_back(0);
for(int head=0;head<(int)queue.size();++head){
int u=queue[head];
for(int i=0;i<(int)e[u].size();++i){
int v=e[u][i];
if(v!=parent[u]){
depth[v]=depth[u]+1;
parent[v]=u;
queue.push_back(v);
}
}
}
}
//step
for(int i=1;i<D;++i)
for(int j=0;j<n;++j){
int &x=pa[i][j];
x=pa[i-1][j];
if(~x)x=pa[i-1][x];
}
fill(qu,qu+n,vector<int>());
for(int i=0;i<m;++i){
scanf("%d%d",a+i,b+i);
--a[i];--b[i];
qu[lca(a[i],b[i])].push_back(i);
}
for(int i=0;i<n;++i)f[i]=i;
int ans=0;
for(int x=n-1;x>=0;--x){
int u=queue[x];
bool found=false;
for(int y=0;y<(int)qu[u].size()&&!found;++y){
int i=qu[u][y];
if(find(a[i])==u&&find(b[i])==u){
found=true;
}
}
if(!found){
f[u]=pa[0][u];
}else{
ans++;
}
}
printf("%d\n",ans);
}
return 0;
}