HDU2208唉,可爱的小朋友 (DFS)

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");

    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值