题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5305
题面:
2 3 3 1 2 2 3 3 1 4 4 1 2 2 3 3 4 4 1
0 2
解题:
因为28本来就不大,很容易想到搜索,但是直接搜是会超时的,加一个当一个人的现实或者虚拟好友数大于其本身关系数一半时,就返回的剪枝即可。注意开始可以直接判一个人关系数为奇,那么就不比进行搜索了。
代码:
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
int t,n,m,cnt_net[10],cnt_real[10],cnt_all[10],a,b,ans,fm[40],to[40];
void dfs(int No,bool status)
{
a=fm[No];
b=to[No];
if(status)
{
cnt_real[a]++;
cnt_real[b]++;
if((cnt_real[a]>cnt_all[a]/2)||(cnt_real[b]>cnt_all[b]/2))
return;
}
else
{
cnt_net[a]++;
cnt_net[b]++;
if((cnt_net[a]>cnt_all[a]/2)||(cnt_net[b]>cnt_all[b]/2))
return;
}
if(No==m)
{
bool sign=true;
for(int i=1;i<=n;i++)
{
if(cnt_real[i]!=cnt_net[i])
{
sign=false;
break;
}
}
if(sign)ans++;
return;
}
dfs(No+1,1);
cnt_real[fm[No+1]]--;
cnt_real[to[No+1]]--;
dfs(No+1,0);
cnt_net[fm[No+1]]--;
cnt_net[to[No+1]]--;
}
int main()
{
scanf("%d",&t);
while(t--)
{
bool flag=true;
ans=0;
scanf("%d%d",&n,&m);
memset(cnt_net,0,sizeof(cnt_net));
memset(cnt_real,0,sizeof(cnt_real));
memset(cnt_all,0,sizeof(cnt_all));
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
fm[i]=a;
to[i]=b;
cnt_all[a]++;
cnt_all[b]++;
}
for(int i=1;i<=n;i++)
{
if(cnt_all[i]%2)
{
flag=false;
break;
}
}
if(!flag)
{
printf("0\n");
continue;
}
if(m)
{
dfs(1,0);
cnt_net[fm[1]]--;
cnt_net[to[1]]--;
// cout<<cnt_net[fm[1]]<<" "<<cnt_net[to[1]]<<endl;
dfs(1,1);
}
else ans=1;
printf("%d\n",ans);
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/david_jett/article/details/47054659