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;
}
posted @ 2008-09-10 20:45  Hdu-Lost  阅读(678)  评论(2编辑  收藏  举报