先对所有的路径求取lca,然后按照lca从大到小的顺序选取路径
若一条路径p1的lca(p1) 的深度大于p2的lca(p2),那么若p1和p2出现冲突,那么p1一定包含p2的lca(p2),那么p2只可能与以lca(p2)为子树中的路径冲突,而p1要冲突的范围更大,两个的贡献同样是1,如果存在一棵比lca(p1)和lca(p2)深度都大的子树中的子树中路径,如果它和p1不冲突,却和p2冲突,那么它已经将p2淘汰,但不会影响p1的选取,所以当前贪心策略是正确的.
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#define MAX 200007
using namespace std;
int ce , cq;
struct edge
{
int v,next;
}e[MAX<<1];
struct query
{
int u,v,next,lca,dep;
bool operator < ( const query& a ) const
{
return dep > a.dep;
}
}q[MAX<<1];
int head1[MAX];
int head2[MAX];
int depth[MAX];
void adde ( int u , int v )
{
e[ce].v = v;
e[ce].next = head1[u];
head1[u] = ce++;
}
void addq ( int u , int v )
{
q[cq].u = u;
q[cq].v = v;
q[cq].next = head2[u];
head2[u] = cq++;
}
int fa[MAX];
int find ( int x )
{
return fa[x] == x ? x : fa[x] = find ( fa[x] );
}
void lca ( int u = 1 , int p = -1 )
{
for ( int i = head1[u] ; i != -1 ; i = e[i].next )
{
int v = e[i].v;
if ( v == p ) continue;
lca ( v , u );
fa[v] = u;
}
for ( int i = head2[u] ; i != -1 ; i = q[i].next )
{
int v = q[i].v;
q[i].lca = q[i^1].lca = find ( v );
q[i].dep = q[i^1].dep = depth[q[i].lca];
}
}
bool vis[MAX];
int pa[MAX];
void dfs ( int u = 1 , int p = -1 , int deep = 1 )
{
depth[u] = deep;
if ( p == -1 ) pa[u] = u;
else pa[u] = p;
for ( int i = head1[u] ; i != -1 ; i = e[i].next )
{
int v = e[i].v;
if ( v == p ) continue;
dfs ( v , u , deep + 1 );
}
}
void paint ( int i , int u )
{
int lca = q[i].lca;
while ( u != lca )
vis[u] = 1 , u = pa[u];
u = q[i].v;
while ( u != lca )
vis[u] = 1 , u = pa[u];
vis[lca] = 1;
}
bool judge ( int i , int u )
{
int lca = q[i].lca;
if ( vis[u] || vis[lca] || vis[q[i].v] ) return false;
while ( u != lca )
{
// cout<< u << "vis :" << vis[u] << endl;
if ( vis[u] ) return false;
else u = pa[u];
}
u = q[i].v;
while ( u != lca )
{
// cout << u << " vis : " << vis[u] << endl;
if ( vis[u] ) return false;
else u = pa[u];
}
if ( vis[lca] ) return false;
return true;
}
int main ( )
{
int n,m,u,v;
while ( ~scanf ( "%d%d" , &n , &m ) )
{
ce = cq = 0;
memset ( head1 , -1 , sizeof ( head1 ));
memset ( head2 , -1 , sizeof ( head2 ));
memset ( vis , 0 , sizeof ( vis ) );
for ( int i = 1 ; i <= n ; i++ ) fa[i] = i;
for ( int i = 1 ; i < n ; i++ )
{
scanf ( "%d%d" , &u , &v );
adde ( u , v );
adde ( v , u );
}
for ( int i = 0 ; i < m ; i++ )
{
scanf ( "%d%d" , &u , &v );
addq ( u , v );
addq ( v , u );
}
dfs ();
lca ();
sort ( q , q+2*m );
int ans = 0;
// for ( int i = 1 ; i <= n ; i++ )
// cout << i <<" : " << pa[i] << endl;
for ( int i = 0 ; i < cq ; i++ )
{
//if ( !vis[q[id].u] && !vis[q[id].v] && !vis[q[id].lca] )
if ( judge ( i , q[i].u ) )
{
// cout << q[id].u << " " << q[id].v << endl;
// cout << "YES" << endl;
ans++;
paint ( i , q[i].u );
}
// for ( int i = 1 ; i <= n ; i ++ )
// cout << vis[u] << " ";
// cout << endl;
}
printf ( "%d\n" , ans );
}
}