CF734E Anton and Tree(并查集,树的直径)

Link

我们可以将同一颜色的连通块缩成点。

然后我们就得到了一棵黑白相间的树。

树的直径的一半即为答案

ps:树的直径,先从随便一个点出发找到最远的点,再从最远的点走到这个点的最远的点,即为树的直径

#include <bits/stdc++.h>
using namespace std ;
const int MAXN = 200000 + 5 ;
int color[ MAXN ] , fa[ MAXN ] , n ;
struct Node {
    int next , to , w ;
} edge[ MAXN << 1 ] ;
int head[ MAXN ] , cnt ;
inline int read () {
    int tot = 0 , f = 1 ; char c = getchar () ;
    while ( c < '0' || c > '9' ) { if ( c == '-' ) f = -1 ; c = getchar () ; }
    while ( c >= '0' && c <= '9' ) { tot = tot * 10 + c - '0' ; c = getchar () ; }
    return tot * f ;
}
inline void add ( int x , int y ) {
    edge[ ++ cnt ].next = head[ x ] ;
    edge[ cnt ].to = y ;
    head[ x ] = cnt ;
}
inline int find ( int k ) {
    if ( fa[ k ] == k ) return k ;
    else return fa[ k ] = find ( fa[ k ] ) ;
}
int maxdeep , maxu ;
inline void dfs ( int deep , int u , int father ) {
    if ( deep > maxdeep ) maxdeep = deep , maxu = u ;
    for ( int i = head[ u ] ; i ; i = edge[ i ].next ) {
        int v = edge[ i ].to ;
        if ( v == father ) continue ;
        dfs ( deep + 1 , v , u ) ;
    }
}
int a[ MAXN ] , b[ MAXN ] ;
signed main () {
    n = read () ;
    for ( int i = 1 ; i <= n ; i ++ ) {
        color[ i ] = read () ;
        fa[ i ] = i ;
    }
    for ( int i = 1 ; i < n ; i ++ ) {
        a[ i ] = read () ; b[ i ] = read () ;
        int fx = find ( a[ i ] ) , fy = find ( b[ i ] ) ;
        if ( color[ fx ] == color[ fy ] ) fa[ fx ] = fa[ fy ] ;
    }
    for ( int i = 1 ; i <= n ; i ++ )
        fa[ i ] = find ( fa[ i ] ) ;
    for ( int i = 1 ; i <= n ; i ++ )
        if ( fa[ a[ i ] ] != fa[ b[ i ] ] )
            add ( fa[ a[ i ] ] , fa[ b[ i ] ] ) , add ( fa[ b[ i ] ] , fa[ a[ i ] ] ) ;
    dfs ( 0 , fa[ 1 ] , 0 ) ;
    dfs ( 0 , maxu , 0 ) ;
    printf ( "%d\n" , ( maxdeep + 1 ) / 2 ) ;
}
posted @ 2020-11-01 21:22  hulean  阅读(106)  评论(0编辑  收藏  举报