码迷,mamicode.com
首页 > 其他好文 > 详细

CF1228F One Node is Gone

时间:2019-10-02 16:29:49      阅读:98      评论:0      收藏:0      [点我收藏+]

标签:class   nod   continue   判断   size   href   namespace   lock   lin   

题目链接

问题分析

这题感觉就是有很多种方法,然后一种都写不明白……

首先分为3种情况:

  • 删了根节点下的一个节点,对应两个答案;
  • 删了一个叶节点,对应一个答案;
  • 删了一个其他节点,对应一个答案。

可以从叶子向上一层一层处理。第一个情况比较好判断;剩下两种情况通过对应节点儿子的个数来判断。注意第二种情况叶节点最大深度差只能是1,其他的点不能有深度差(毕竟是完全二叉树)。

面向数据编程

参考程序

#include <bits/stdc++.h>
//#include <unistd.h>
using namespace std;
 
const int Maxn = 131100;
struct edge {
    int To, Next;
    edge() {}
    edge( int _To, int _Next ) : To( _To ), Next( _Next ) {}
};
edge Edge[ Maxn << 1 ];
int Start[ Maxn ], Used;
inline void AddEdge( int x, int y ) {
    Edge[ ++Used ] = edge( y, Start[ x ] );
    Start[ x ] = Used;
    return;
}
int deep, n;
int Deg[ Maxn ], Dep[ Maxn ], Deep, Son[ Maxn ];
int Rec[ Maxn ], Left, Vis[ Maxn ];
int Ans[ 10 ];
 
int main() {
    scanf( "%d", &deep );
    n = 1; for( int i = 1; i <= deep; ++i ) n *= 2; n -= 2;
    memset( Deg, 0, sizeof( Deg ) );
    for( int i = 1; i < n; ++i ) {
        int x, y;
        scanf( "%d%d", &x, &y );
        AddEdge( x, y );
        AddEdge( y, x );
        ++Deg[ x ]; ++Deg[ y ];
    }
 
    Left = n;
    Deep = 1;
    for( int i = 1; i <= n; ++i )
        if( Deg[ i ] == 1 ) 
            Dep[ i ] = Deep;
 
    while( Left > 1 ) {
        //printf( "========================================\n" );
        //printf( "Deg B:\n" );
        //for( int i = 1; i <= n; ++i ) printf( "%d ", Deg[ i ] );
        //printf( "\n" );
        Rec[ 0 ] = 0;
        for( int i = 1; i <= n; ++i ) 
            if( Deg[ i ] == 1 ) {
                Rec[ ++Rec[ 0 ] ] = i;
                if( Son[ i ] != 3 && Dep[ i ] != Deep ) {
                    printf( "0\n" );
                    return 0;
                }
                if( Son[ i ] == 3 && Dep[ i ] + 1 != Deep ) {
                    printf( "0\n" );
                    return 0;
                }
                if( Son[ i ] != 2 && Son[ i ] != 0 ) {
                    if( Ans[ 0 ] ) {
                        printf( "0\n" );
                        return 0;
                    }
                    Ans[ ++Ans[ 0 ] ] = i;
                }
            }
        //printf( "Rec %d\n", Rec[ 0 ] );
        //for( int i = 1; i <= Rec[ 0 ]; ++i ) printf( "%d ", Rec[ i ] );
        //printf( "\n" );
 
        if( Rec[ 0 ] == 2 && Left == 2 ) {
            if( Ans[ 0 ] ) {
                printf( "0\n" );
                return 0;
            }
            printf( "2\n%d %d\n", Rec[ 1 ], Rec[ 2 ] );
            return 0;
        }
        
        for( int i = 1; i <= Rec[ 0 ]; ++i )
            Vis[ Rec[ i ] ] = 1;
 
        for( int i = 1; i <= Rec[ 0 ]; ++i ) {
            int u = Rec[ i ];
            for( int t = Start[ u ]; t; t = Edge[ t ].Next ) {
                int v = Edge[ t ].To;
                if( Vis[ v ] ) continue;
                --Deg[ u ]; --Deg[ v ];
                ++Son[ v ];
                if( Dep[ v ] == 0 ) Dep[ v ] = Deep + 1;
            }
        }
        
        Left -= Rec[ 0 ];
        ++Deep;
        //printf( "Deg A:\n" );
        //for( int i = 1; i <= n; ++i ) printf( "%d ", Deg[ i ] );
        //printf( "\n" );
        //printf( "Left = %d\n", Left );
        //printf( "Son:\n" );
        //for( int i = 1; i <= n; ++i ) printf( "%d ", Son[ i ] );
        //printf( "\n" );
        //printf( "Ans = %d\n", Ans[ 0 ] );
        //sleep( 3 );
    }
 
    printf( "1\n%d\n", Ans[ 1 ] );
 
    return 0;
}

CF1228F One Node is Gone

标签:class   nod   continue   判断   size   href   namespace   lock   lin   

原文地址:https://www.cnblogs.com/chy-2003/p/11617540.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!