破冰派对(搜索)




时间限制:2s 空间限制:256M

看到这个题,我们可以发现它的约束条件比较严格,所以答案很有可能没有或者合法解的个数很少qwq,所以这个时候带剪枝的搜索很有可能跑得过。

就是dfs啦!!借鉴图的思路,我们把认识的人先连边,之后搜索的时候我们考虑一个一个同学遍历,另开一个参数来记录是否选择为管理员。

剪枝1:若当前选择的同学和已经选择的管理员不认识就return;(他一定不会成为管理员)

剪枝2:若当前选择的同学和没有选择的(也就是参与者)认识就return;(他一定不会成为管理员)

之后对于那种约束条件松的同学,就考虑两种情况(他可以选择成为管理员也可以成为参与者)进行dfs即可。

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#define MAXN 2010
using namespace std;
int done[MAXN][MAXN],cur[MAXN];
int n,m,t,ans;
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=x*10+ch-'0';
		ch=getchar();
	}
	return x*f;
}
inline void search(int x,int y)
{
	if(x>n)
    {
		if(y!=0&&y!=n)
			ans++;
		return;
    }
	bool flag1=1,flag2=1;
	for(register int j=1;j<x;j++) 
    {
		if(cur[j])
		{
			if(done[x][j]==0)
				flag1=0;
		}
		else   
            if(done[x][j]==1)
				flag2=0;
    }
	if(flag1) 
        cur[x]=1,search(x+1,y+1);
	if(flag2)
        cur[x]=0,search(x+1,y);
}
int main()
{
	freopen("party.in","r",stdin);
	freopen("party.out","w",stdout);
	scanf("%d",&t); 
	while(t--)
    {
		memset(done,0,sizeof(done));
		memset(cur,0,sizeof(cur));
		n=read();m=read();
		for(register int i=1;i<=m;i++)
        {
			int x,y;
			x=read(); y=read();
            done[x][y]=done[y][x]=1;
        }   
        ans=0;
        search(1,0);
		printf("%d\n",ans);
	}
	return 0;
}
posted @ 2018-10-13 07:53  风浔凌  阅读(452)  评论(0编辑  收藏  举报