[HDU 4997 Biconnected] 无向图的边双联通子图计数 状压DP
来源:互联网 发布:优酷视频下载器 mac 编辑:程序博客网 时间:2024/04/29 10:20
题目
http://acm.hdu.edu.cn/showproblem.php?pid=4997
分析
无向图的边双联通子图计数 状压DP
膜拜了SJTU的代码
用联通的子图个数减去非双联通子图的个数
1.联通子图的个数的做法
用connected[s]表示点集s的子图的联通子图的个数
用cntEdge[s]表示s中的边数,cntEdge[s1][s2]表示s1和s2之间的边数,那么
connected[s] = 2^cntEdge[s] - connected[s'] * 2^cntEdge[s-s']
s'为包含同一个点的联通子图,包含同一个点是为了避免重复,即将一个联通子集剥离出来的方案数
2.非双联通子图的做法
想法是用一个包含同一个点的双联通子图用树边去连接若干个联通子图
用expand[s1][s2]表示以集合s2通过树边连接s1的方案数,其中s2是s1的子集,那么
expand[s1][s2] = sigma{connected[s'] * cntEdge[s'][s2] * expand[s1 - s'][s2]},其中s'为s1的子集
3.双联通子图的做法
设biconnected[s]表示点集s的子图的边双联通子图个数,那么
biconnected[s] = connect[s] - biconnected[s'] * expand[s][s']
s'为包含同一个点的双联通子图
代码
/************************************************** * Problem: HDU 4997 * Author: clavichord93 * State: Accepted **************************************************/#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>using namespace std;const int MAX_N = 10;const int MAX_S = 1 << MAX_N;const int Mod = (int)1e9 + 7;int n, m;bool edge[MAX_N][MAX_N];int cntEdge[MAX_S][MAX_S];long long connected[MAX_S];long long biconnected[MAX_S];long long expand[MAX_S][MAX_S];int main() { #ifdef LOCAL_JUDGE freopen("in.txt", "r", stdin); #endif int T; scanf("%d", &T); for (int cas = 1; cas <= T; cas++) { scanf("%d %d", &n, &m); memset(edge, true, sizeof(edge)); for (int i = 1; i <= m; i++) { int a, b; scanf("%d %d", &a, &b); a--; b--; edge[a][b] = false; edge[b][a] = false; } for (int i = 0; i < n; i++) { edge[i][i] = false; } int cntState = 1 << n; for (int i = 0; i < cntState; i++) { for (int j = 0; j < cntState; j++) { if (i == j || (i & j) == 0) { int &ref = cntEdge[i][j]; ref = 0; for (int x = 0; x < n; x++) { if ((i >> x) & 1) { int low = (i == j) ? x + 1 : 0; for (int y = low; y < n; y++) { if ((j >> y) & 1) { ref += edge[x][y]; } } } } } } } connected[0] = 1; biconnected[0] = 1; for (int mask = 1; mask < cntState; mask++) { int lowbit = mask & -mask; { long long &ref = connected[mask]; ref = 1ll << cntEdge[mask][mask]; for (int subset = mask ^ lowbit; subset; subset = (subset - 1) & (mask ^ lowbit)) { ref -= connected[mask ^ subset] * (1ll << cntEdge[subset][subset]); } } { for (int target = mask ^ lowbit; target; target = (target - 1) & (mask ^ lowbit)) { int source = mask ^ target; int _lowbit = target & -target; long long &ref = expand[mask][source]; ref = 0; for (int subset = target ^ _lowbit; ; subset = (subset - 1) & (target ^ _lowbit)) { int set = target ^ subset; ref += connected[set] * cntEdge[set][source] * expand[mask ^ set][source]; if (subset == 0) { break; } } } expand[mask][mask] = 1; } { long long &ref = biconnected[mask]; ref = connected[mask]; for (int subset = mask ^ lowbit; subset; subset = (subset - 1) & (mask ^ lowbit)) { ref -= biconnected[mask ^ subset] * expand[mask][mask ^ subset]; } } } int ans = biconnected[cntState - 1] % Mod; printf("%d\n", ans); } return 0;}
0 0
- [HDU 4997 Biconnected] 无向图的边双联通子图计数 状压DP
- BZOJ1002 无向联通图的生成树计数
- 无向图的边双联通分量,点双联通分量
- HDU 4738 Caocao's Bridges(找无向图的桥 双联通)
- 图方法:二分无向图的联通子图查找
- hdoj 4738 Caocao's Bridges 【无向图边-双联通 求所有桥中权值最小的】
- 求无向图中的桥 和 边的双联通分量
- hdu 4997 Biconnected
- HDU-6184 (无向图三元环计数)
- 无向图的联通分量NEUACM1134: Searching for TwoBee
- 求无向联通图的割点
- hdu 2242(图的双联通&树形dp)
- HDOJ 4612 - Warm up tarjan求无向图双联通分量+树形DP+stack申请更多空间
- 无向图的割顶、桥和双联通分量
- 无向连通图至少增加多少边形成双联通
- 无向图的连通子图
- [无向图简单环计数 状压DP] Codeforces 11D Beta Round #11 D. A Simple Task
- HDU 3094 无向图的删边游戏
- java中抽象类跟接口的区别
- 关于dbv的 run selected revisions 没有反应
- SSH面试
- Pow(x, n)
- Win7 Java环境变量配置方法
- [HDU 4997 Biconnected] 无向图的边双联通子图计数 状压DP
- 进步的阶梯(1)---生成可执行jar包
- Qt on Android:使用JNI与第三方jar包
- wp8 application.resources 加入
- 【淘宝数据干货】我用数据告诉你互联网安全套行业是什么样的?【不看后悔!!!】
- Redmine 访问太缓慢--问题解决
- ajaxSubmit 上传成功 保存json文件 问题解决
- 你们说这样对吗?
- 我在网上收集的开源android app学习网址