把这题想复杂了,一直在考虑怎么快速的判断将选的边和已选的边无冲突,后来经人提醒发现这根本没必要,反正数据也不大开两个数组爆搜就OK了,搜索之前要先排除两种没必要搜的情况,这很容易想到,爆搜的时候注意几个小细节就可以了(代码代码注释中已标好)
#include<cstdio> #include<cstring> #include<iostream> #include<vector> #include<utility> using namespace std; typedef pair<int,int> P; vector<int> gt[30]; int g[36][36]; int c0[36],c1[36]; 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+1,x+2); // 注意这里不是从1开始 原因很简单 因为前面的都已经标记过了 } else if(g[x][y]) { c0[x]++; c0[y]++; // 注意这里是y 把一条边划分之后,两个点都被划分了 dfs(x,y+1); c0[x]--; c0[y]--; c1[x]++; c1[y]++; dfs(x,y+1); c1[x]--; c1[y]--; } else if(g[x][y]==0) dfs(x,y+1); } int main() { int t; scanf("%d",&t); while(t--) { count=0; scanf("%d%d",&n,&m); memset(g,0,sizeof(g)); memset(c1,0,sizeof(c1)); memset(c0,0,sizeof(c0)); for(int k=1;k<=n;k++) gt[k].clear(); for(int i=0;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]=1; } int f=0; for(int j=1;j<=n;j++) { if(gt[j].size()%2) f=1; } if(f||m%2) { printf("0\n"); continue; } dfs(1,2); // 0 代表 网络 1代表现实 printf("%d\n",count); } }
,无脑不许想太多、、、、
时间: 2024-10-12 22:47:06