暴搜-hdu-2208-唉,可爱的小朋友

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=2208

题目大意:

有n个小朋友,之间有相互喜欢的关系,如果A喜欢B的话,输入时保证B一定喜欢A。现在有m个小气球,问能否分成不超过m组,每组不存在有两个小朋友互相不喜欢。

解题思路:

因为不具有传递性,所以不属于双联通。

又n很小,所以直接暴搜。

fa[i]=j表示i是属于j为根的集合。  不能用贪心,先把一个小朋友的满足的最大的朋友全部去掉。。。这种思路是错的,要全局搜索。

代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#define eps 1e-6
#define INF 0x1f1f1f1f
#define PI acos(-1.0)
#define ll __int64
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;


//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);

#define Maxn 15
int fa[Maxn];
bool edge[Maxn][Maxn];
int n,m;

bool dfs(int a,int mm) //a表示第几个小朋友,mm表示前面用了多少个气球
{
   if(mm>m)
      return false;//气球用超了
   if(a==n)//表示小朋友已经安排完了
      return true;
   for(int i=0;i<a;i++) //扫描前面有多少个集合
   {
      if(fa[i]!=i)
         continue;
      bool flag=true;
      for(int j=0;j<a&&flag;j++)
         if(fa[j]==i)
            flag=edge[j][a];
      if(flag)
      {
         fa[a]=i;
         if(dfs(a+1,mm))
            return true; //往后扫
         fa[a]=a;//不放到该集合里去
      }
   }
   if(dfs(a+1,mm+1)) //单独作为一个集合
      return true;
   return false;
}

int main()
{
   while(~scanf("%d%d",&n,&m))
   {
      memset(edge,false,sizeof(edge));
      for(int i=0;i<n;i++)
      {
         int k,a;
         scanf("%d",&k);
         for(int j=0;j<k;j++)
            scanf("%d",&a),edge[i][a]=true;
      }
      for(int i=0;i<n;i++)
         fa[i]=i;
      if(m>=n||dfs(0,0))
         printf("YES\n");
      else
         printf("NO\n");
   }
   return 0;
}



你可能感兴趣的:(搜索)