破冰派对(搜索)
时间限制: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;
}