传送门:【HDU】4912 Paths on the tree
题目分析:优先选择深度高的路径一定不劣于优先选择深度底的路径,于是我们用tarjan离线求出每条路径的lca,然后对lca的深度从大到小排序,然后挨个判断是否可以这条路径和之前选择的路径冲突(无冲突即路径两个端点均未被标记),如果无冲突,++ans且将这条路径的lca对应的子树上的点都标记为被选择状态。
代码如下:
#include <map> #include <vector> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std ; typedef long long LL ; #pragma comment ( linker , "/STACK:1024000000" ) #define rep( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i ) #define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i ) #define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i ) #define rec( i , A , o ) for ( int i = A[o] ; i != o ; i = A[i] ) #define clr( a , x ) memset ( a , x , sizeof a ) const int MAXN = 100005 ; const int MAXE = 200005 ; const int INF = 0x3f3f3f3f ; struct Edge { int v , n ; Edge () {} Edge ( int v , int n ) : v ( v ) , n ( n ) {} } ; struct Query { int v , idx , n ; Query () {} Query ( int v , int idx , int n ) : v ( v ) , idx ( idx ) , n ( n ) {} } ; struct Node { int u , v , lca , dep ; Node () {} Node ( int u , int v , int lca , int dep ) : u ( u ) , v ( v ) , lca ( lca ) , dep ( dep ) {} bool operator < ( const Node& a ) const { return dep > a.dep ; } } ; Edge E[MAXE] ; Query query[MAXE] ; Node node[MAXN] ; int H[MAXN] , cntE ; int Q[MAXN] , cntQ ; int vis[MAXN] , Time ; int pre[MAXN] ; int dep[MAXN] ; int p[MAXN] ; int n , m ; void clear () { cntE = cntQ = 0 ; pre[1] = 0 ; dep[1] = 0 ; clr ( H , -1 ) ; clr ( Q , -1 ) ; } void addedge ( int u , int v ) { E[cntE] = Edge ( v , H[u] ) ; H[u] = cntE ++ ; } void addquery ( int u , int v , int idx ) { query[cntQ] = Query ( v , idx , Q[u] ) ; Q[u] = cntQ ++ ; } int find ( int x ) { return p[x] == x ? x : ( p[x] = find ( p[x] ) ) ; } void tarjan ( int u ) { p[u] = u ; vis[u] = Time ; for ( int i = H[u] ; ~i ; i = E[i].n ) { int v = E[i].v ; if ( v == pre[u] ) continue ; pre[v] = u ; dep[v] = dep[u] + 1 ; tarjan ( v ) ; p[v] = u ; } for ( int i = Q[u] ; ~i ; i = query[i].n ) { int v = query[i].v, idx = query[i].idx ; if ( vis[v] == Time ) { int lca = find ( v ) ; node[idx] = Node ( u , v , lca , dep[lca] ) ; } } } void visit ( int u , int fa ) { vis[u] = Time ; for ( int i = H[u] ; ~i ; i = E[i].n ) { int v = E[i].v ; if ( v == pre[u] || vis[v] == Time ) continue ; visit ( v , u ) ; } } void solve () { int u , v , ans = 0 ; clear () ; rep ( i , 1 , n ) { scanf ( "%d%d" , &u , &v ) ; addedge ( u , v ) ; addedge ( v , u ) ; } For ( i , 1 , m ) { scanf ( "%d%d" , &u , &v ) ; addquery ( u , v , i ) ; addquery ( v , u , i ) ; } ++ Time ; tarjan ( 1 ) ; ++ Time ; sort ( node + 1 , node + m + 1 ) ; For ( i , 1 , m ) if ( vis[node[i].u] != Time && vis[node[i].v] != Time ) { visit ( node[i].lca , pre[node[i].lca] ) ; ++ ans ; } printf ( "%d\n" , ans ) ; } int main () { clr ( vis , 0 ) ; Time = 0 ; while ( ~scanf ( "%d%d" , &n , &m ) ) solve () ; return 0 ; }