把这题想复杂了,一直在考虑怎么快速的判断将选的边和已选的边无冲突,后来经人提醒发现这根本没必要,反正数据也不大开两个数组爆搜就OK了,搜索之前要先排除两种没必要搜的情况,这很容易想到,爆搜的时候注意几个小细节就可以了(代码代码注释中已标好)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<utility>
using namespace std;
typedef pair<int,int> P; vector<int> gt[];
int g[][];
int c0[],c1[];
int count;
int n,m;
void dfs(int x,int y)
{
if(x>n)
{
count++;
// printf("%d\n",count);
return;
}
else if(y>n)
{
if(c0[x]!=c1[x]) return;
dfs(x+,x+); // 注意这里不是从1开始 原因很简单 因为前面的都已经标记过了
}
else
if(g[x][y])
{
c0[x]++;
c0[y]++; // 注意这里是y 把一条边划分之后,两个点都被划分了
dfs(x,y+);
c0[x]--;
c0[y]--; c1[x]++;
c1[y]++;
dfs(x,y+);
c1[x]--;
c1[y]--;
}
else if(g[x][y]==) dfs(x,y+);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
count=;
scanf("%d%d",&n,&m);
memset(g,,sizeof(g));
memset(c1,,sizeof(c1));
memset(c0,,sizeof(c0));
for(int k=;k<=n;k++)
gt[k].clear();
for(int i=;i<m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
gt[a].push_back(b);
gt[b].push_back(a);
g[a][b]=g[b][a]=;
}
int f=;
for(int j=;j<=n;j++)
{
if(gt[j].size()%) f=;
}
if(f||m%)
{
printf("0\n");
continue;
}
dfs(,); // 0 代表 网络 1代表现实
printf("%d\n",count);
}
}

,无脑不许想太多、、、、

05-28 06:18