hdu 4912Paths on the tree (LCA)
解法:求出询问的lca,把询问根据lca的深度排序。深度深的先选,选了之后,把以当前询问的lca为根的子树全部打上vis标记,后选的边如果左右两端点有任何一个是有vis标记的就不选。
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std ;
const int maxn = 111111 ;
struct Edge {
int to , next ;
} edge[maxn<<1] ;
int head[maxn] , tot , f[maxn<<1] ;
void new_edge ( int a , int b ) {
edge[tot].to = b ;
edge[tot].next = head[a] ;
head[a] = tot ++ ;
}
struct LCA {
int dp[22][maxn<<1] ;
int to[maxn] , tim[maxn] ;
int tot , n ;
int MIN ( int a , int b ) {
return tim[a] < tim[b] ? a : b ;
}
void init () {
tot = 0 ;
n = 0 ;
}
void dfs ( int u , int fa ) {
tim[u] = ++ tot ;
for ( int i = head[u] ; i != -1 ; i = edge[i].next ) {
int v = edge[i].to ;
if ( v == fa ) continue ;
dfs ( v , u ) ;
dp[0][++n] = u ;
}
dp[0][++n] = u ;
to[u] = n ;
}
void rmq () {
for ( int i = 1 ; i <= 20 ; i ++ ) {
for ( int j = 1 ; j + (1<<i) - 1 <= n ; j ++ ) {
dp[i][j] = MIN ( dp[i-1][j] , dp[i-1][j+(1<<i-1)] ) ;
}
}
}
int query ( int a , int b ) {
a = to[a] , b = to[b] ;
if ( a > b ) swap ( a , b ) ;
int k = b - a + 1 ;
return MIN ( dp[f[k]][a] , dp[f[k]][b-(1<<f[k])+1] ) ;
}
} lca ;
int vis[maxn] , deep[maxn] ;
void dfs ( int u , int fa ) {
deep[u] = deep[fa] + 1 ;
for ( int i = head[u] ; i != -1 ; i = edge[i].next ) {
int v = edge[i].to ;
if ( v == fa ) continue ;
dfs ( v , u ) ;
}
}
void mark ( int u ) {
vis[u] = 1 ;
for ( int i = head[u] ; i != -1 ; i = edge[i].next ) {
int v = edge[i].to ;
if ( vis[v] || deep[u] > deep[v] ) continue ;
mark ( v ) ;
}
}
struct ANS {
int l , r , u ;
bool operator < ( const ANS& p ) const {
return deep[u] > deep[p.u] ;
}
} fuck[maxn] ;
void init () {
memset ( head , -1 , sizeof ( head ) ) ;
tot = 0 ;
memset ( vis , 0 , sizeof ( vis ) ) ;
}
int main () {
int n , m ;
f[0] = -1 ;
for ( int i = 1 ; i < maxn<<1 ; i ++ )
f[i] = f[i>>1] + 1 ;
while ( scanf ( "%d%d" , &n , &m ) != EOF ) {
init () ;
lca.init () ;
for ( int i = 1 ; i < n ; i ++ ) {
int a , b ;
scanf ( "%d%d" , &a , &b ) ;
new_edge ( a , b ) ;
new_edge ( b , a ) ;
}
lca.dfs ( 1 , 0 ) ;
lca.rmq () ;
dfs ( 1 , 0 ) ;
for ( int i = 1 ; i <= m ; i ++ ) {
scanf ( "%d%d" , &fuck[i].l , &fuck[i].r ) ;
fuck[i].u = lca.query ( fuck[i].l , fuck[i].r ) ;
}
sort ( fuck + 1 , fuck + m + 1 ) ;
int ans = 0 ;
for ( int i = 1 ; i <= m ; i ++ ) {
if ( !vis[fuck[i].l] && !vis[fuck[i].r] ) {
ans ++ ;
mark ( fuck[i].u ) ;
}
}
printf ( "%d\n" , ans ) ;
}
return 0 ;
}
/*
7 10
1 3
1 5
2 3
3 4
5 6
5 7
12 1000
1 2
1 4
1 5
2 9
2 3
4 8
5 6
5 11
5 12
6 7
6 10
7 3
1 2
1 3
2 4
2 5
3 6
3 7
2 3
4 5
6 7
*/