Loading

题解—Strange Housing

\(link\)

这为什么是道绿题啊,让我这种想不到的人很卑微

题目让构造一组满足题意的合法方案。

首先图本身不联通必定无解。

若图联通,我们考虑构造一个图的 \(dfs\) 树,让所有的点通过这个树联通,那么所有的点必定在图里面也联通。

什么方案能让所有的点在树上联通呢,只需要在树上进行染色。

假设被染成黑色是我们要选择的,被染成白色是不选择的。

那假设我们给一个点染成黑色,那么根据题目要求,他周围的点要染成白色。

也就是,如果一个点的周围已经有黑色点,那么我们只能给他染成白色。

除此情况,我们都可以染成黑色。

证明一下为什么这个方案成立。

  • 首先,所有连接黑点和白点的边保证了黑点和白点联通。也就是,我们只需要保证白点和白点联通就行了。

  • 根据我们的构造方法,一条边被删掉当且仅当两边都是白点(我们假设是点 \(A\) 和点 \(B\) ),那么 \(A\)\(B\) 必定有边联通黑点,且这两个黑点必然联通,否则 \(A\)\(B\) 不会同时为白点。

Code

#include <cstdio>
#include <algorithm>
#include <cstring>
#define R register int
#define scanf Ruusupuu = scanf
#define freopen rsp_5u = freopen

int Ruusupuu ;
FILE * rsp_5u ;

using namespace std ;
typedef long long L ;
typedef double D ;
const int N = 3e5 + 10 ;

inline void of(){ freopen( "in.in" , "r" , stdin ) , freopen( "out.out" , "w" , stdout ) ; }
inline void cf(){ fclose( stdin ) , fclose( stdout ) ; }
inline int read(){
	int w = 0 ; bool fg = 0 ; char ch = getchar() ;
	while( ch < '0' || ch > '9' ) fg |= ( ch == '-' ) , ch = getchar() ;
	while( ch >= '0' && ch <= '9' ) w = ( w << 1 ) + ( w << 3 ) + ( ch - '0' ) , ch = getchar() ; 
	return fg ? -w : w ;
}

int T , n , m , color [N] , vis[N] , x , y ;
int fr [N << 1] , to [N << 1] , net [N << 1] , head [N] , cnt = 1 ;
#define add( f , t ) fr [++ cnt] = f , to [cnt] = t , net [cnt] = head [f] , head [f] = cnt

void sc(){
	T = read() ;
}

void clear(){
	n = read() , m = read() , cnt = 1 ;
	for( R i = 1 ; i <= n ; i ++ ) head [i] = -1 , color [i] = vis [i] = 0 ;
	for( R i = 1 ; i <= m ; i ++ ) x = read() , y = read() , add( x , y ) , add( y , x ) ;
}

void dfs( int x ){
	vis [x] = 1 ;
	bool fg = 0 ;
	for( R i = head [x] ; ~i ; i = net [i] ) 
		if( color [to [i]] == 1 ) fg = 1 ;
		
	if( fg ){
		color [x] = 2 ;
		for( R i = head [x] ; ~i ; i = net [i] )
			if( !vis [to [i]] ) dfs( to [i] ) ;
	}
	
	else{
		color [x] = 1 ;
		for( R i = head [x] ; ~i ; i = net [i] )
			if( !vis [to [i]] ) color [to [i]] = 2 , dfs( to [i] ) ;
	}

}

void work(){
	dfs( 1 ) ;
	int ans = 0 ;
	for( R i = 1 ; i <= n ; i ++ ) 
		if( !color [i] ) return puts( "NO" ) , void() ;
		else if( color [i] == 1 ) ans ++ ;  
	printf( "YES\n%d\n" , ans ) ;
	for( R i = 1 ; i <= n ; i ++ ) 
		if( color [i] == 1 ) printf( "%d " , i ) ;
	puts( "" ) ;
}

signed main(){
//	of() ;
	sc() ;
	while( T -- ){
		clear() ;
		work() ;
	}
//	cf() ;
	return 0 ;
}
posted @ 2021-08-02 15:27  Soresen  阅读(56)  评论(0)    收藏  举报