hdu 5305 Friends(2015多校第二场第6题)记忆化搜索

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5305

题意:给你n个人,m条关系,关系可以是online也可以是offline,让你求在保证所有人online关系的朋友和offline关系的朋友相等的情况下,这样的情况有多少种。

思路:因为online关系和offline关系的人数相等,而且m最多才28,所以只要枚举每个人的一半的关系是否符合要求即可,而且根据题意m是奇数或者有一个人的总关系为奇数那么就没有符合要求的情况,这样可以排除很多情况。

代码:

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iostream>
#include <queue>
#include <algorithm>
#include <vector>
using namespace std;
#define LL __int64

int f[10],on[10],off[10];
int m,n;
struct node
{
    int x,y;
}nn[30];
void init()
{
    memset(f,0,sizeof(f));
    memset(on,0,sizeof(on));
    memset(off,0,sizeof(off));
}
int dfs(int cot)
{
    int x,y,i,ans;
    ans=0;
    if(cot>=m)
    {
        for(i=1;i<=n;i++)
        {
            if(on[i]!=off[i])
                return 0;
        }
        return 1;
    }
    x=nn[cot].x;
    y=nn[cot].y;
    if(on[x]<f[x]/2&&on[y]<f[y]/2)
    {
        on[x]++;
        on[y]++;
        ans+=dfs(cot+1);
        on[x]--;
        on[y]--;
    }
    if(off[x]<f[x]/2&&off[y]<f[y]/2)
    {
        off[x]++;
        off[y]++;
        ans+=dfs(cot+1);
        off[x]--;
        off[y]--;
    }
    return ans;
}

int main()
{
    int i,T,ans;
    while(~scanf("%d",&T))
    {
        while(T--)
        {
            scanf("%d%d",&n,&m);
            init();
            for(i=0;i<m;i++)
            {
                scanf("%d%d",&nn[i].x,&nn[i].y);
                f[nn[i].x]++;
                f[nn[i].y]++;
            }
            if(m&1)
            {
                printf("0\n");
                continue;
            }
            int flag=0;
            for(i=1;i<=n;i++)
            {
                if(f[i]&1)
                {
                    flag=1;
                    break;
                }
            }
            if(flag)
            {
                printf("0\n");
                continue;
            }
            ans=dfs(0);
            printf("%d\n",ans);
        }
    }
    return 0;
}


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