题目链接: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; }