破冰派对(搜索)




时间限制: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;
}

猜你喜欢

转载自www.cnblogs.com/fengxunling/p/9781556.html