http://acm.hdu.edu.cn/showproblem.php?pid=5305
此题我们是先推出 边数m 如果为奇数必然不符合条件。只能为偶数。筛选掉了一半
其次 因为最多8个点,所有最多能构成的图,只有24条边。。
也就是当m>25 ans=0(怎么也无法构成符合条件的图)
然后对1-20 条边的情况下。暴力跑: 每条边用0或1表示这是online边还是offline边。复杂度2^n. 对于因为奇数不可以,只剩下22 24,我们已经推出了24条边是可以的。并且只有一种连法(需要判断一下是否为此连法)。。暴力跑出了答案是2648、只要边数=24且是那一种连法就输出2648,对于22我们也推出22条边是无法构成合法图的,其余情况暴力跑就可以了。。。数据不大。所以也水过了
比较正确的算法应该是 按边来用dfs跑。。加上剪枝也能过
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include<stdlib.h>
#include <queue>
#include <set>
#include <vector>
#define MAX 100
#define inf 0x3f3f3f3f
using namespace std;
#define tree_size MAX*3
struct edge
{
int a,b,stu;
}A[MAX];
int num[10];
int d[10];
int u[10];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
// if(m==0)
// printf("%d\n",1)
memset(num,0,sizeof(num));
for(int i=0;i<m;i++)
{
scanf("%d%d",&A[i].a,&A[i].b);
num[A[i].a]++;
num[A[i].b]++;
}
if(m%2||m>24||m==22)
{
printf("0\n");
continue;
}
int flag=0;
for(int i=1;i<=n;i++)
{
if(num[i]%2)
{
flag=1;
break;
}
}
if(flag)
{
printf("0\n");
continue;
}
if(m==24)
{
flag=0;
for(int i=1;i<=8;i++)
{
if(num[i]!=6)
{
flag=1;
break;
}
}
if(!flag)
{
printf("2648\n");
continue;
}
else
{
printf("0\n");
continue;
}
}
int s=pow(2.0,m)-1;
int ans=0;
for(int i=0;i<=s;i++)
{
memset(u,0,sizeof(u));
memset(d,0,sizeof(d));
int temp=i;
for(int j=0;j<m;j++)
{
if(temp%2==0)
A[j].stu=0;
else
A[j].stu=1;
temp/=2;
}
for(int k=0;k<m;k++)
{
if(A[k].stu==0)
{
d[A[k].a]++;
d[A[k].b]++;
}
else
{
u[A[k].a]++;
u[A[k].b]++;
}
}
ans++;
for(int j=1;j<=n;j++)
{
if(d[j]!=u[j])
{
ans--;
break;
}
}
}
printf("%d\n",ans);
}
return 0;
}