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;
}
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;
}