Problem Description
唉,小朋友是比较麻烦的。在一个幼儿园里,老师要上一节游戏课,有N个小朋友要玩游戏,做游戏时要用小皮球,但是幼儿园里只有M个小皮球,而且有些小朋友不喜欢和一些小朋友在一起玩,而只喜欢和另一些小朋友一起玩,比如傻妞只喜欢和傻瓜,傻根,傻蛋们一起玩,傻根又不喜欢和傻蛋一起玩,傻蛋喜欢和傻子一起玩。所以老师只好把他们分组,每个组至少有一个小球可以玩,而且每个组内不会有两个小朋友,相互不喜欢。现在给你这样一个幼儿园里小朋友之间关系的描述,做为老师,是否可以上好这节游戏课。
Input
数据有多个case,每个case先输入两个值N(1<=N<=10)和M(1<=M<=10),表示有N个小朋友(从0到N-1标号),和M个小皮球。接着有N行,第i行先输入一个K(0<=K<N),表示第i个小朋友有喜欢一起玩的其他小朋友的个数,然后后面有K个整数,表示K个小朋友的标号(不重复)。如果A喜欢和B一起玩,则B也喜欢和A一起玩,这个数据在输入时保证。两个case之间有空行
Output
对于每个case,如果老师可以上好课,输出YES,否则NO。
Sample Input
3 2
2 1 2
2 2 0
2 0 1
Sample Output
YES
在本题的评论区看到有个人的思路,我觉得挺好的,但是自己用C写一直WA,然后,提交了评论区这个人的答案,提示也有表达错误。实在是找不到错误,希望如果有人能找到错误,可以悄咪咪的告诉一下我呀! 哈哈哈!!!我终于找到了自己的错误!!!AC啦!!!
自己找到的错误:
1.visited[MAX]数组不小心定义为bool类型
2.dfs函数的if语句里,visited[v]不小心写成了visited[i]
具体思路就是:
有m个小皮球和n个小朋友,小朋友是0~N-1号。
1.把每个小皮球看成一组,通过小皮球来进行递归遍历。
2.假设我们成功地把v号小朋友放进1号小皮球组,然后再进入一次dfs,把v+1号小朋友放进1号小皮球组,如果v+1号小朋友不能放进1号小皮球组,就把v+1号小朋友放进2号小皮球组,……,如果前面都失败了,就退回来,把v号小朋友放进2号小皮球组,直到如果找到了一个满足的方式,就返回true,否则如果所有情况都不成立,就返回false。
#include<stdio.h>
#include<string.h>
#define MAX 11
int n,m;
bool map[MAX][MAX];
int visited[MAX];//第i号小朋友进的组号
bool check(int v,int tag)//第v号小朋友想进第tag组
{
for(int i=0;i<n;i++)
if(i!=v&&visited[i]==tag&&map[v][i]==false)//i号小朋友玩tag号球,但是i号小朋友不喜欢v号小朋友
return false;
return true;
}
bool dfs(int v)
{
if(v>=n) //n个小朋友都有组了,递归结束,找到了可以找的答案
return true;
else
{
for(int i=1;i<=m;i++)//选择每个皮球作为分组
{
if(visited[v]==0&&check(v,i))//判断v号小朋友是否可以进i号皮球组
{
visited[v]=i;//加入第i组
if(dfs(v+1))//看看后面的小盆友可不可以成功
return true;
visited[v]=0;//没有成功,那么就不加入第i组
}
}
}
return false;
}
int main()
{
while(scanf("%d %d",&n,&m)!=EOF)
{
memset(map,false,sizeof(map));//false表示假设他们直接不喜欢一起玩
memset(visited,0,sizeof(visited));
int k,like;
for(int i=0;i<n;i++)
{
scanf("%d",&k);
for(int j=0;j<k;j++)
{
scanf("%d",&like);
map[i][like]=true;
map[like][i]=true;
}
}
if(m>=n)//球的数量大于等于小孩的数量,肯定可以玩
printf("YES\n");
else
{
if(dfs(0))
printf("YES\n");
else printf("NO\n");
}
}
}
贴一个测评数据:
6 2
3 1 4 5
3 0 2 3
2 1 3
2 1 2
2 0 5
2 0 4
YES
再贴一个我最开始的时候的错误写法,很容易看出,如果按照我下面的思路,下面的这张图就会出现这样的错误答案(其中一个颜色的圈圈代表一组):
#include<stdio.h>
#include<string.h>
#define MAX 11
int n,m;
bool map[MAX][MAX];
int visited[MAX];//0表示没有找过,其他数字表示玩第i号球
int tag;//标记目前是第i号球
bool check(int v)
{
for(int i=0;i<n;i++)
if(visited[i]==tag&&map[v][i]==false)//i号小朋友玩tag号球,但是i号小朋友不喜欢v号小朋友
return false;
return true;
}
void dfs(int v)
{
visited[v]=tag;
for(int i=0;i<n;i++)
if(!visited[i]&&check(i))
dfs(i);
}
int main()
{
while(scanf("%d %d",&n,&m)!=EOF)
{
memset(map,false,sizeof(map));//false表示假设他们直接不喜欢一起玩
int k,like;
for(int i=0;i<n;i++)
{
scanf("%d",&k);
for(int j=0;j<k;j++)
{
scanf("%d",&like);
map[i][like]=true;
}
}
int cnt=0;
tag=0;
memset(visited,0,sizeof(visited));
for(int i=0;i<n;i++)
if(visited[i]==0)
{
cnt++;
tag++;
dfs(i);
}
if(cnt<=m)
printf("YES\n");
else printf("NO\n");
}
}