HDU 2208(dfs枚举)

自己写了半天 WA了很多次

后来就请教了留上星

题目意思就是需要使用到并查集的 然后进行顶点着色似的枚举 很简单的枚举 不过暴力的实在不会 只好重新学习学习了

代码如下

 

 

#include  < iostream >
using   namespace  std;
bool  hash[ 20 ][ 20 ];
long  root[ 20 ];
long  N,M;
bool  finish;
void  dfs( long  m,  long  s)
{
    
if  (finish) // 已经可以分配完
    {
        
return ;
    }
    
if  (s  >  M) // 用的球太多了
    {
        
return ;
    }
    
if  (m  ==  N) // 人已经加完
    {
        finish 
=   true ; // 此时球未分完 那就完成了
         return ;
    }
    
int  i, j, fg;
    
for  (i  =   0 ; i  <  m; i ++ )
    {
        
if  (root[i]  !=  i) // 如果第i个人不是集合代表
             continue // 继续找代表
        fg  =   1 ;
        
for  (j  =  i; j  <  m  &&  fg; j ++
            fg 
=   ! (root[j]  ==  i  &&  (hash[m][j]  ==   0   ||  hash[j][m]  ==   0 )); // 如果i所在集合里的所有人都不拒绝m
         if  (fg)
        {
            root[m] 
=  i; // 令m就属于i这个集合
            dfs(m  +   1 , s); // 继续加下一个人
            root[m]  =  m; // m还原 继续枚举下个集合
        }
    }
    dfs(m 
+   1 , s  +   1 ); // 加入下一个人 多放一个球的情况
}


bool  check()
{
    
    
long  i;
    
    finish
= false ;
    
    
for  (i = 0 ;i < N; ++ i)
    {
        root[i]
= i;
    }
    
    dfs(
0 , 0 );
    
    
if  (finish)
    {
        
return   true ;
    }
    
    
return   false ;
}

int  main()
{
    
    
while  (scanf( " %ld %ld " , & N, & M) != EOF)
    {

        memset(hash,
0 , sizeof (hash));

        
long  i,j;
        
for  (i = 0 ;i < N; ++ i)
        {
            
long  n;
            scanf(
" %ld " , & n);
            
for  (j = 0 ;j < n; ++ j)
            {
                
long  t;
                scanf(
" %ld " , & t);
                hash[i][t]
= true ;
            }
        }

        
if  (N <= M || check())
        {
            puts(
" YES " );
        }
        
else
        {
            puts(
" NO " );
        }


    }
    
return   0 ;
}

你可能感兴趣的:(HDU)