0w1

GCJ 2014 R1A pB. Full Binary Tree ( DFS )

Dashboard - Round 1A 2014 - Google Code Jam
題目中一個合法的完全樹的定義是,所有節點的子節點數為0或2。要求的是移除最少點使得給定的樹成為完全樹。因為數據範圍小,可以考慮枚舉每個節點作為根,再做一次線性的深搜處理。根據定義可以得到遞迴函數,如果一個節點的子節點數為0則花費為0,如果為1則花費為該子樹的節點數總和,如果為2則花費為兩個子樹分別的子問題的花費總和。如果更多,那麼先考慮如果選出兩個子節點 a和 b保留,那麼花費是所有子節點的節點數總和減去 a和 b子樹的節點數總和,再加上 a和 b兩個子問題的花費總和。由於所有子節點的節點數這部分是固定的,所以要找的是最小的兩個 a和 b使得,-( a, b子樹size ) + ( a, b子樹cost )最小。

#include <bits/stdc++.h>
using namespace std;
const int MAXT = 100 + 2;
const int MAXN = 1e3 + 3;

int kase;
int n;
vector< int > G[ MAXN ];

void init( int _n ){
    for( int i = 1; i <= _n; ++i )
        G[ i ].clear();
}

int getSize( int u, int fa ){
    int res = 0;
    for( int v : G[ u ] ){
        if( v == fa ) continue;
        res += getSize( v, u );
    }
    return res + 1;
}

int dfs( int u, int fa ){
    if( G[ u ].size() - ( fa > 0 ) == 0 )
        return 0;
    if( G[ u ].size() - ( fa > 0 ) == 1 ){
        for( int v : G[ u ] ){
            if( v == fa ) continue;
            return getSize( v, u );
        }
    }
    if( G[ u ].size() - ( fa > 0 ) == 2 ){
        int res = 0;
        for( int v : G[ u ] ){
            if( v == fa ) continue;
            res += dfs( v, u );
        }
        return res;
    }
    int sz_sum = 0;
    int min1 = 0, min2 = 0;
    for( int v : G[ u ] ){
        if( v == fa ) continue;
        int v_sz = getSize( v, u );
        int val = -v_sz + dfs( v, u );
        if( val < min1 ){
            min2 = min1;
            min1 = val;
        } else if( val < min2 )
            min2 = val;
        sz_sum += v_sz;
    }
    return sz_sum + min1 + min2;
}

void solve(){
    int ans = n;
    for( int i = 1; i <= n; ++i ){
        ans = min( ans, dfs( i, -1 ) );
        // printf("%d : %d\n", i, dfs( i, -1 ));
    }
    printf("%d\n", ans);
}

int main(){
    int T; scanf("%d", &T);
    for( kase = 1; kase <= T; ++kase ){
        printf("Case #%d: ", kase);
        scanf("%d", &n);
        init( n );
        for( int i = 0; i < n - 1; ++i ){
            int u, v; scanf("%d%d", &u, &v);
            G[ u ].push_back( v );
            G[ v ].push_back( u );
        }
        solve();
    }
    return 0;
}