HDU 5305 Friends(dfs)

来源:互联网 发布:喵翻网络连接失败 编辑:程序博客网 时间:2024/05/17 18:26
Problem Description
There are n people and m pairs of friends. For every pair of friends, they can choose to become online friends (communicating using online applications) or offline friends (mostly using face-to-face communication). However, everyone in these n people wants to have the same number of online and offline friends (i.e. If one person has x onine friends, he or she must have x offline friends too, but different people can have different number of online or offline friends). Please determine how many ways there are to satisfy their requirements. 
 

Input
The first line of the input is a single integer T (T=100), indicating the number of testcases. 

For each testcase, the first line contains two integers n (1n8) and m (0mn(n1)2), indicating the number of people and the number of pairs of friends, respectively. Each of the next m lines contains two numbers x and y, which mean x and y are friends. It is guaranteed that xy and every friend relationship will appear at most once. 
 

Output
For each testcase, print one number indicating the answer.
 

Sample Input
23 31 22 33 14 41 22 33 44 1
 

Sample Output
02
 

Author
XJZX
 

Source
2015 Multi-University Training Contest 2
 
题意:
给出n个点,m条边,n<=8,m<=n*(n-1)/2,
所有边有2个属性,要求每个点所拥有两种属性的边的数量相等
问有多少种方案
分析:
最多有28条边,假设边的属性为a,b那么只需dfs枚举每条边的属性(a或b)
最后检查是否每个点两种属性的边的数量相等
剪枝操作:1.若某个点拥有的边为奇数个,答案为0
  2.在枚举过程中若点x的a属性的边已经大于等于点x拥有的总边数,那么x的边不能再是a是属性(否则构不成满意的方案)
#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<queue>#define mem(a,x) memset(a,x,sizeof(a))using namespace std;typedef long long ll;const int inf = 1<<29;const int N = 10;int a[N+5],b[N+5];//记录每个点边属性的数量vector<int>u[N+5];//记录每个点拥有的边struct Edge{    int u,v;}e[30];//先将边保存起来最后枚举int n,m;ll ans;bool ok()//是否满足每个点的两种属性的边数量相等{    for (int i = 1;i <= 8;++i)    {        if (a[i]!=b[i]) return 0;    }    return 1;}void dfs(int p)//枚举每条边的属性{    if (p == m)    {        if (ok()) ans++;        return;    }    int x = e[p].u,y = e[p].v;//这条边连着的两个点    if (a[x] < u[x].size()/2&&a[y] < u[y].size()/2)//不足一半    {                                            //判此边为a属性        a[x]++;        a[y]++;        dfs(p+1);//下一条边        a[x]--;        a[y]--;    }    if (b[x]<u[x].size()/2&&b[y]<u[y].size()/2)    {        b[x]++;        b[y]++;        dfs(p+1);        b[x]--;        b[y]--;    }}int main(){    int T;scanf("%d",&T);    while (T--)    {        scanf("%d %d",&n,&m);        for (int i = 1;i <= 8;++i) u[i].clear();        for (int i = 0;i < m;++i)        {            scanf("%d %d",&e[i].u,&e[i].v);            u[e[i].v].push_back(e[i].u);            u[e[i].u].push_back(e[i].v);        }        bool fd = 0;        for (int i = 0;i <= 8;++i)        {            if (u[i].size()%2)//奇数            {                fd = 1;                break;            }        }        if (fd)        {            puts("0");            continue;        }        ans = 0;mem(a,0);mem(b,0);        dfs(0);        printf("%lld\n",ans);    }    return 0;}


0 0