hdu 5305 Friends(dfs)

题意:n个人m条边(n<=8),对于每个点所连的边有0,1两种权值,且对于每个点两种边的数量要相等,问该图有几种方式;

思路:记录连在每个点上的边数,每种边的数量恰为1/2的总边数;

         枚举每一条边,该边有两种状态,dfs遍历每一种状态,每一个满足条件的图为一种方式,两种边数量相等为条件;

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int T,n,m;
int s[5050],t[5050];
int on[5050],off[5050];
int du[5050],ans,cnt;
void dfs(int x)
{
    if(x==m+1)
    {
        for(int i=1;i<=n;i++){
            if(on[i]!=off[i]){
                 return;
            }
        }
       ans++;return;
    }
    if((on[s[x]]<du[s[x]]/2)&&(on[t[x]]<du[t[x]]/2)){ //能用除法不用乘法
        on[s[x]]++,on[t[x]]++;
        dfs(x+1);
        on[s[x]]--,on[t[x]]--;
    }
    if((off[s[x]]<du[s[x]]/2)&&(off[t[x]]<du[t[x]]/2)){
        off[s[x]]++,off[t[x]]++;
        dfs(x+1);
        off[s[x]]--,off[t[x]]--;
    }
}
int main()
{
    int i,j,k;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        memset(on,0,sizeof(on));
        memset(off,0,sizeof(off));
        memset(du,0,sizeof(du));
        for(i=1;i<=m;i++){
            scanf("%d%d",&s[i],&t[i]);
            du[s[i]]++;du[t[i]]++;
        }
        ans=0;cnt=1;
        dfs(1);
        printf("%d\n",ans);
    }
    return 0;
}

 

你可能感兴趣的:(HDU)