JZOJ4513. 【JSOI2016】独特的树叶

来源:互联网 发布:伞 知乎 编辑:程序博客网 时间:2024/05/15 22:30

题目大意

给两棵树,分别有nn+1个节点。已知其中一棵树比另一棵多一个叶子节点。求编号最小的可能多出来的节点编号。

Data Constraint
1N105

题解

先将树求一个hash(异或一下随便乱搞),然后可以再移根把原树所有可能的hash值求出来,存在一个map里。对于新树,把所有度数为1的节点删掉后看map里是否有相同的hash,求个最小值就行了。

SRC

#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#include<map>using namespace std ;#define N 100000 + 10typedef unsigned long long ll ;const ll Pri = 1e9 + 7 ;map < ll , bool > S ;ll Hash[N] ;int Node[2*N] , Next[2*N] , Head[N] , tot ;int c[N] , Size[N] ;int n , ans = 0x7FFFFFFF ;void link( int u , int v ) {    Node[++tot] = v ;    Next[tot] = Head[u] ;    Head[u] = tot ;}void Build( int x , int F ) {    Size[x] = 1 ;    for (int p = Head[x] ; p ; p = Next[p] ) {        if ( Node[p] == F ) continue ;        Build( Node[p] , x ) ;        Hash[x] = Hash[x] ^ (Hash[Node[p]] + 17) ;        Size[x] += Size[Node[p]] ;    }    Hash[x] += Size[x] * Pri + 1 ;}void DFS( int x , int F ) {    S[Hash[x]] = 1 ;    for (int p = Head[x] ; p ; p = Next[p] ) {        if ( Node[p] == F ) continue ;        ll Ne = ((Hash[x] - n * Pri - 1) ^ (Hash[Node[p]] + 17))  + (n - Size[Node[p]]) * Pri + 1 ;        Hash[Node[p]] = ((Hash[Node[p]] - Pri * Size[Node[p]] - 1) ^ (Ne + 17)) + n * Pri + 1 ;        Size[Node[p]] = n ;        DFS( Node[p] , x ) ;    }}void Search( int x , int F ) {    for (int p = Head[x] ; p ; p = Next[p] ) {        if ( Node[p] == F ) continue ;        if ( c[Node[p]] > 1 ) {            ll Ne = ((Hash[x] - Size[x] * Pri - 1) ^ (Hash[Node[p]] + 17))  + (Size[x] - Size[Node[p]]) * Pri + 1 ;            Hash[Node[p]] = ((Hash[Node[p]] - Pri * Size[Node[p]] - 1) ^ (Ne + 17)) + Size[x] * Pri + 1 ;            Size[Node[p]] = Size[x] ;            Search( Node[p] , x ) ;        } else {            ll Ne = ((Hash[x] - Size[x] * Pri - 1) ^ (Hash[Node[p]] + 17))  + (Size[x] - 1) * Pri + 1 ;            if ( S.count(Ne) ) ans = min( ans , Node[p] ) ;        }    }}int main() {    scanf( "%d" , &n ) ;    for (int i = 1 ; i < n ; i ++ ) {        int u , v ;        scanf( "%d%d" , &u , &v ) ;        link( u , v ) ;        link( v , u ) ;    }    Build( 1 , 0 ) ;    DFS( 1 , 0 ) ;    tot = 0 ;    memset( Head , 0 , sizeof(Head) ) ;    for (int i = 1 ; i <= n ; i ++ ) {        int u , v ;        scanf( "%d%d" , &u , &v ) ;        c[u] ++ , c[v] ++ ;        link( u , v ) ;        link( v , u ) ;    }    memset( Size , 0 , sizeof(Size) ) ;    memset( Hash , 0 , sizeof(Hash) ) ;    int st = 1 ;    for ( ; st <= n ; st ++ ) if ( c[st] > 1 ) break ;    Build( st , 0 ) ;    Search( st , 0 ) ;    printf( "%d\n" , ans ) ;    return 0 ;}

以上.

1 0
原创粉丝点击