hdu 5305 回溯+剪枝
2015-07-23 20:48
357 查看
思路:对每一条边涂上颜色1或-1,颜色值加到关联的两个点上,则一种成功的方案必须满足最后每个点的值为0.
剪枝:统计出和某个点i相关联的边的个数,如果枚举到某一条边的时候发现:abs(sum[i]) > degree[i],则剪去,其中sun[i]表示i点的值,degree[i]表示剩下的还没有枚举的和i关联的边的个数。
剪枝:统计出和某个点i相关联的边的个数,如果枚举到某一条边的时候发现:abs(sum[i]) > degree[i],则剪去,其中sun[i]表示i点的值,degree[i]表示剩下的还没有枚举的和i关联的边的个数。
#include <iostream> #include <cstring> #include <cstdio> using namespace std; const int N = 9; const int M = 28; int sum ; int degree ; int n, m, ans; struct Edge { int u, v; } edge[M]; int judge() { for ( int i = 1; i <= n; i++ ) { if ( sum[i] ) return 0; } return 1; } int abs( int x ) { return x > 0 ? x : -x; } void dfs( int cur ) { if ( cur == m ) { ans += judge(); return ; } for ( int i = 1; i <= n; i++ ) { if ( abs(sum[i]) > degree[i] ) return ; } int u = edge[cur].u, v = edge[cur].v; degree[u]--; degree[v]--; sum[u]++; sum[v]++; dfs( cur + 1 ); sum[u]--; sum[v]--; sum[u]--; sum[v]--; dfs( cur + 1 ); sum[u]++; sum[v]++; degree[u]++; degree[v]++; } int main () { int t; scanf("%d", &t); while ( t-- ) { scanf("%d%d", &n, &m); memset( degree, 0, sizeof(degree) ); for ( int i = 0; i < m; i++ ) { scanf("%d%d", &edge[i].u, &edge[i].v); degree[edge[i].u]++; degree[edge[i].v]++; } bool flag = false; for ( int i = 1; i <= n; i++ ) { if ( degree[i] & 1 ) { flag = true; break; } } ans = 0; if ( !flag ) { memset( sum, 0, sizeof(sum) ); dfs(0); } printf("%d\n", ans); } return 0; }
相关文章推荐
- 毕业之后实习公司的选择
- 微信公众平台开发时需要判断微信浏览器访问
- 虚幻4如何通过C++创建UObject或者UClass
- Scala入门到精通——第八节 包和引入
- dijk
- CentOS 6.6安装Mysql
- 细节啊细节
- hdu-2115(结构体,sort) I Love This Game
- Android 拍照或从相册取图片并裁剪
- String与InputStream相互转换
- 第二篇,REST风格介绍
- 多校第二场 1006 hdu 5305 Friends(爆搜)
- <q>和<blockquote>的区别
- OC07 -- 迭代器/NSNumber/NSValue/NSRange/NSSet/NSDate 及相互转换.(杂)
- LCA 交通运输线 题目&题解&代码
- SDN,该怎么学习?
- jqGrid列表控件基本应用
- IOS键盘收放以及通知
- Android 将多个RadioGroup合成一个
- 递归算法、File类、输入输出流、XML解析