*HDU 5305 - Friends (DFS + 剪枝)

题目:

http://acm.hdu.edu.cn/showproblem.php?pid=5305

题意:

n个人,m条边,每个人与他连边的人的关系有两种,两种关系的人数必须相同,求出方案数。

思路:

由于n<=8,m<=(8*7/2) = 28,因为每个人确定了1/2边之后剩下的边也就确定了,所有只要枚举 一半的边即可。

BFS,该边选或者不选。

AC.

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>

using namespace std;
int to[10], n, m, d[10], num;
int u[100], v[100];

int dfs(int x)
{
    if(num*2 >= m) {
        for(int i = 1; i <= n; ++i) {
            if(d[i]*2 != to[i]) return 0;
        }
        return 1;
    }

    int ans = 0;
    if(d[u[x]]*2 < to[u[x]] && d[v[x]]*2 < to[v[x]]) {
        num++;
        d[u[x]]++; d[v[x]]++;
        ans += dfs(x+1);
        num--;
        d[u[x]]--; d[v[x]]--;
    }
    if(m/2 - num < m - x)
        ans += dfs(x+1);
    return ans;
}

int judge()
{
    for(int i = 1; i <= n; ++i) {
        if(to[i] % 2) return 0;
    }

    memset(d, 0, sizeof(d));
    num = 0;
    return dfs(0);
}

int main()
{
    //freopen("in", "r", stdin);
    int T;
    scanf("%d", &T);
    while(T--) {
        memset(to, 0, sizeof(to));

        scanf("%d%d", &n, &m);
        for(int i  = 0; i < m; ++i) {
            scanf("%d %d", &u[i], &v[i]);
            to[u[i]] ++;
            to[v[i]] ++;
        }

        printf("%d\n", judge());
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值