题解—Strange Housing
这为什么是道绿题啊,让我这种想不到的人很卑微
题目让构造一组满足题意的合法方案。
首先图本身不联通必定无解。
若图联通,我们考虑构造一个图的 \(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 ;
}
$The \ light \ has \ betrayed \ me$

浙公网安备 33010602011771号