传送门:【POJ】2114 Boatherds
题目分析:2333又水了一道题。。
问是否存在长度等于K的路径。就是将统计小于等于K的换成统计等于K的条数,只要最后统计出来的等于K的数量大于0就是存在。其他一点没变,还是那个点分治,还是曾经的味道~
代码如下:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std ; typedef long long LL ; #define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next ) #define rep( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i ) #define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i ) #define FOR( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i ) #define clr( a , x ) memset ( a , x , sizeof a ) #define cpy( a , x ) memcpy ( a , x , sizeof a ) const int MAXN = 10005 ; const int MAXE = 20005 ; struct Edge { int v , c ; Edge* next ; } E[MAXE] , *H[MAXN] , *edge ; bool vis[MAXN] ; int dep[MAXN] ; int siz[MAXN] ; int num[MAXN] ; int S[MAXN] ; int weight ; int root ; int top ; int ans ; int n , K ; void clear () { edge = E ; clr ( H , 0 ) ; } void addedge ( int u , int v , int c ) { edge -> v = v ; edge -> c = c ; edge -> next = H[u] ; H[u] = edge ++ ; } void get_root ( int u , int fa = 0 ) { siz[u] = 1 ; num[u] = 0 ; travel ( e , H , u ) { int v = e -> v ; if ( !vis[v] && v != fa ) { get_root ( v , u ) ; siz[u] += siz[v] ; num[u] = max ( num[u] , siz[v] ) ; } } num[u] = max ( num[u] , weight - siz[u] ) ; if ( num[u] < num[root] ) root = u ; } void get_dep ( int u , int fa = 0 ) { if ( dep[u] <= K ) S[top ++] = dep[u] ; siz[u] = 1 ; travel ( e , H , u ) { int v = e -> v ; if ( !vis[v] && v != fa ) { dep[v] = dep[u] + e -> c ; get_dep ( v , u ) ; siz[u] += siz[v] ; } } } int get_num ( int u , int initial_dep ) { top = 0 ; dep[u] = initial_dep ; get_dep ( u ) ; sort ( S , S + top ) ; int l = 0 , r = top - 1 , res = 0 ; while ( l < r ) { if ( S[l] + S[r] > K ) -- r ; else if ( S[l] + S[r] < K ) ++ l ; else { if ( S[l] == S[r] ) { res += ( r - l + 1 ) * ( r - l ) / 2 ; break ; } int i = l , j = r ; while ( S[l] == S[i] ) ++ i ; while ( S[r] == S[j] ) -- j ; res += ( i - l ) * ( r - j ) ; l = i , r = j ; } } return res ; } void dfs ( int u ) { vis[u] = 1 ; ans += get_num ( u , 0 ) ; travel ( e , H , u ) { int v = e -> v ; if ( !vis[v] ) { ans -= get_num ( v , e -> c ) ; root = 0 ; weight = siz[v] ; get_root ( v ) ; dfs ( root ) ; } } } void solve () { int x , c ; clear () ; FOR ( i , 1 , n ) { while ( ~scanf ( "%d" , &x ) && x ) { scanf ( "%d" , &c ) ; addedge ( i , x , c ) ; addedge ( x , i , c ) ; } } while ( ~scanf ( "%d" , &K ) && K ) { clr ( vis , 0 ) ; ans = root = 0 ; weight = num[0] = n ; get_root ( 1 ) ; dfs ( root ) ; printf ( ans ? "AYE\n" : "NAY\n" ) ; } printf ( ".\n" ) ; } int main () { while ( ~scanf ( "%d" , &n ) && n ) solve () ; return 0 ; }