【HDU】4912 Paths on the tree 离线LCA+贪心

传送门:【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 ;
}


你可能感兴趣的:(HDU)