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
这道题在我看来还是有点难的,首先我要把他的数据结构当做是无向图,因为a喜欢b就等于b喜欢a。
其实就是判断无向图的连通个数是否小于皮球的个数吧,后来发现我这个思路写不下去,所以就参考了别人的思路.
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
using namespace std;
//有m个小皮球和n个小朋友,小朋友是0~N-1号。
//1.把每个小皮球看成一组,通过小皮球来进行递归遍历。
//2.假设我们成功地把v号小朋友放进1号小皮球组,
//然后再进入一次dfs,把v+1号小朋友放进1号小皮球组,
//如果v+1号小朋友不能放进1号小皮球组,就把v+1号小朋友放进2号小皮球组,
//……,如果前面都失败了,就退回来,把v号小朋友放进2号小皮球组,
//直到如果找到了一个满足的方式,就返回true,否则如果所有情况都不成立,就返回false。
int n,m;//n个小朋友,m个球
bool map[100][100];//判断两个小朋友之间是否有连线
int visted[100];//小朋友进的组号
int i;
bool check(int x,int zu){//判断x小朋友能否进入zu组
for(i=0;i<n;i++){
//遍历所有除了他之外,已经在这个组的小朋友,并且和他不喜欢的
if(i!=x&&visted[i]==zu&&map[i][x]==false)
return false;
else
return true;
}
return false;
}
bool dfs(int v){
if(v>=n)
return true;//说明之前的n个小朋友都已经组好队了
else{
for(i=1;i<=m;i++){
//选择每个皮球进行循环
if(visted[v]==0&&check(v,i)){//如果这个小朋友目前没有进组,并且他可以进入到这个组
visted[v]=i;//加入这个组
//然后看看后面的小朋友是否都可以这样
if(dfs(v+1))
return true;
visted[v]=0;//那就不加入
}
}
}
return false;
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF){
//初始化
memset(map,false,sizeof(map));
memset(visted,0,sizeof(visted));
//输入每个小朋友喜欢的人
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(dfs(0))
printf("YES\n");
else
printf("No\n");
}
}