hdu 2208 唉,可爱的小朋友

    纠结了这道题很久,开始的时候就想到了用并查集,但是对并查集并不熟悉,所以在网上参考了[这个链接上的内容](http://www.cnblogs.com/jackge/p/3228479.html)
    主要是通过一个dfs,遍历所有的可能,暴力枚举,原文是用c++写的,我改用了java写,其实都是差不多的。
    思路:
     1. 利用一个map二维数组记录所有对应关系。
     2. 利用一个root一维数组记录所有集合的根
     3. dfs开始的条件为0个人,0个球,然后通过dfs逐渐添加人数和球的个数,保证了组成的集合数与球的个数是相等的
     4. 让每一个人都分别属于一个不同的集合。然后判断一个点可不可以放入一个集合里,这时候要找到那个集合的根,同时,要确保这个点不与集合里面的所有点有冲突。同时,一个点可能可以放入多个集合中,那样通过一个dfs,那样就可以枚举出所有的可能,再通过一个判断,就可以知道是否有满足题意的点。
import java.util.Scanner;

/**
 * Created with IntelliJ IDEA
 * Author: HWJ
 * Date: 2016-08-25
 * Time: 8:14
 */
public class Main {
    private static int[] root ;
    private static boolean[][] map;
    private static boolean finish ;
    private static int n,m;


    public static void main(String[]Args) {
        Scanner input = new Scanner(System.in);
        while(input.hasNext()){
            n = input.nextInt();
            m = input.nextInt();
            root = new int[n];
            map = new boolean[n][n];
            finish = false;
            for(int i=0;i<n;i++){
                int K = input.nextInt();
                root[i] = i;
                for(int j=0;j<K;j++){
                    int a = input.nextInt();
                    map[i][a] = true;
                }
            }
            dfs(0,0);
            //当人数小于球数的时候一定可以满足情况
            if(n <= m || finish){ 
                System.out.println("YES");
            }else{
                System.out.println("NO");
            }

        }
    }

    public static void dfs(int x,int y){
        if(finish) { //满足不发生冲突的情况的时候
            return;
        }
        if(y > m) { //当需要的球数超过了实际的球数时
            return;
        }
        if(x == n){//当在现有的球数情况下,人数能全部加完的时候
            finish = true;
            return ;
        }

        for(int i=0;i<x;i++){
            //找出其中一个集合的根
            if(root[i] != i){
                continue;
            }
            boolean fg = true;
            //检测集合中的所有人是否都是接受x这个点的
            for (int j=i;j<x && fg; j++){
                if(root[j] == i){
                    fg = map[j][x];
                }
            }
            if(fg){//fg为true的时候就是所有人都接受x这个点
                root[x] = i;
                dfs(x+1,y); //加一个人,不加球的情况,即集合数不变,加一个人进集合中,不发生冲突
                root[x] = x; //将m还原,放到下一个集合中
            }
        }
        dfs(x+1,y+1);   //加一个人,加一个球的情况,在所有集合都不接受x这个点的时候执行
    }


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值