这题主要是计算连通子图的个数(c)和不连通子图的个数(dc)还有连通度为1的子图的个数(c1)和连通度为2以上的子图的个数(c2)之间的转化关系

主要思路大概例如以下:

用状态压缩的方法算出状态为x的子图的不连通子图个数dc[x],dc[x] = ∑ c[i]*(2^edge[x-i]),i为x的子集且i中有x的编号最小的元素。edge[x] 表示x集合内有几条边

连通子图个数c[x]  = 2^edge[x] - dc[x]

想得到双连通子图的个数就要计算单连通子图的个数

单连通子图缩块后是一棵树,假设每次我们选择标号最小的点所在的块为根节点(块)

那么单连通子图能够看成是在这个双连通的根节点(块)的基础上连接一个连通分量。这样能枚举到全部的情况,也不会反复

mc[s][x] += mc[s][x - y] * c[y] * e[s][y]。当中mc[s][x-y]是指把x-y连接到s的方法数,e[s][y]是指s到y的边数
c1[s] += mc[x][s - x],c1[s]是s中单连通子图的个数

而双连通子图个数 c2[s] = c[s] - c1[s]

最后转回去计算mc[s][0]。意思假设根节点s(块)不拓展连通分量的方法数,就相当于计算根节点(块)为双连通子图的方法数。等于c2[s]

再通过这些值计算mc[s+1][?]的值,不断的往上递推来完毕所有的计算

#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<cmath>
#include<cassert>
#include<cstring>
#include<iomanip>
using namespace std;
#ifdef _WIN32
#define i64 __int64
#define out64 "%I64d\n"
#define in64 "%I64d"
#else
#define i64 long long
#define out64 "%lld\n"
#define in64 "%lld"
#endif
/************ for topcoder by zz1215 *******************/
#define foreach(c,itr)  for(__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)
#define FOR(i,a,b)      for( int i = (a) ; i <= (b) ; i ++)
#define FF(i,a)         for( int i = 0 ; i < (a) ; i ++)
#define FFD(i,a,b)      for( int i = (a) ; i >= (b) ; i --)
#define S64(a)          scanf(in64,&a)
#define SS(a)           scanf("%d",&a)
#define LL(a)           ((a)<<1)
#define RR(a)           (((a)<<1)+1)
#define pb              push_back
#define pf              push_front
#define X               first
#define Y               second
#define CL(Q)           while(!Q.empty())Q.pop()
#define MM(name,what)   memset(name,what,sizeof(name))
#define MC(a,b)     memcpy(a,b,sizeof(b))
#define MAX(a,b)        ((a)>(b)?(a):(b))
#define MIN(a,b)        ((a)<(b)?(a):(b))
#define read            freopen("out.txt","r",stdin)
#define write           freopen("out2.txt","w",stdout)const int inf = 0x3f3f3f3f;
const i64 inf64 = 0x3f3f3f3f3f3f3f3fLL;
const double oo = 10e9;
const double eps = 10e-9;
const double pi = acos(-1.0);
const int mod = 1000000007;
const int maxn = 1 << 10;int n, m;
int a[10][10];
i64 pow2[maxn];
i64 edge[maxn];
i64 ex[10][maxn];
i64 e[maxn][maxn];
i64 dc[maxn];
i64 c[maxn];
i64 c1[maxn];
i64 c2[maxn];
i64 mc[maxn][maxn];
vector<int>vx;
vector<int>v;
vector<int>v2;void start(){MM(edge, 0); MM(dc, 0); MM(c, 0); MM(c1, 0); MM(c2, 0); MM(e, 0); MM(ex, 0); MM(mc, 0);for (int x = 0; x < n; x++){for (int s = 0; s < (1 << n); s++){for (int i = 0; i < n; i++)if (s&(1 << i)){if (!a[x][i]){ex[x][s] ++;}}}}for (int s = 0; s < (1<<n); s++){for (int x = 0; x < (1 << n); x++){for (int i = 0; i < n; i++)if(s&(1<<i)){e[s][x] += ex[i][x];}}}for (int s = 1;s < (1 << n); s++){for (int i = 0; i < n; i++) if(s & (1<<i)){for (int j = i + 1; j < n; j++) if(s& (1<<j)){if (!a[i][j]){edge[s]++;}}}}int head;for (int s = 1; s < (1 << n); s++){v.clear();for (int i = 0; i < n; i++){if (s & (1 << i)){v.push_back((1<<i));}}head = v[0];v.erase(v.begin());int x;for (int i = 0; i < (1 << ((int)v.size())); i++){x = 0;for (int pos = 0; pos < v.size(); pos++){if (i &(1 << pos)) {x += v[pos];}}x += head;if (x != s){dc[s] += c[x] * pow2[edge[s - x]];dc[s] %= mod;}} c[s] = pow2[edge[s]] - dc[s] + mod;c[s] %= mod;  }for (int s = 1; s < (1 << n); s++){vx.clear();v.clear();       int x;for (int i = 0; i < n; i++){if (s & (1 << i)){vx.push_back(1<<i);}}int vxhead = vx[0];vx.erase(vx.begin());for (int i = 0; i < (1 << ((int)vx.size())); i++){x = 0;for (int pos = 0; pos < vx.size(); pos++){if (i&(1 << pos)){x += vx[pos];}}x += vxhead;if (x != s){c1[s] += mc[x][s - x];c1[s] %= mod;}}c2[s] = (c[s] - c1[s]+mod)%mod;mc[s][0] = c2[s];for (int i = 0; i < n; i++){if (s&(1 << i)){head = i;break;}}for (int i = head + 1; i < n; i++){if (!(s&(1 << i))){v.push_back(1<<i);}}for (int i = 1; i < (1 << ((int)v.size())); i++){x = 0;for (int pos = 0; pos < v.size(); pos++){if (i&(1 << pos)){x += v[pos];}}v2.clear();for (int u = 0; u < n; u++){if (x&(1 << u)){v2.push_back(1 << u);}}int y;for (int j = 1; j < (1 << ((int)v2.size())); j++) if(j&1){y = 0;for (int pos = 0; pos < v2.size(); pos++){if (j & (1 << pos)){y += v2[pos];}}mc[s][x] +=(( mc[s][x - y] * c[y])%mod) * e[s][y];mc[s][x] %= mod;}}}}int main(){pow2[0] = 1;for (int i = 1; i < maxn; i++){pow2[i] = pow2[i - 1] * 2;pow2[i] %= mod;}int T;cin >> T;while (T--){cin >> n >> m;MM(a, 0);int x, y;for (int i = 0; i < n; i++){a[i][i] = 1;}for (int i = 1; i <= m; i++){cin >> x >> y;x--; y--;a[x][y] = a[y][x] = 1;}start();cout << c2[(1 << n) - 1] << endl;}return 0;
}

转载于:https://www.cnblogs.com/gcczhongduan/p/5206026.html

hdu 4997 Biconnected相关推荐

  1. HDU 4997 Biconnected (状态压缩DP)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4997 题意:一个n个点的完全图中去掉一些边.求这个图有多少个子图是边双联通的.(就是去掉任意一条边之后 ...

  2. HDU 4389 - X mod f(x)

    题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=4389 2012多校,第9场,1010 . 问题是,询问区间内 存在多少个 哈沙德数(Harshad ...

  3. hdu 4389 囧,打表

    http://acm.hdu.edu.cn/showproblem.php?pid=4389 题意 :一个数能被他各个位数之和整除则符合要求,给L,R,问区间里有多少个数符合要求. 囧,居然打表就能过 ...

  4. HDU——1106排序(istringstream的使用、STLvector练习)

    排序 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submiss ...

  5. hdu 5438 Ponds 拓扑排序

    Ponds Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/contests/contest_showproblem ...

  6. HDU 1248 寒冰王座(全然背包:入门题)

    HDU 1248 寒冰王座(全然背包:入门题) http://acm.hdu.edu.cn/showproblem.php?pid=1248 题意: 不死族的巫妖王发工资拉,死亡骑士拿到一张N元的钞票 ...

  7. hdu 1312 Red and Black 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1312 第二条深搜,题目并不难,但是做了我好久好久,由于一个细节,让我赌上了一个晚上的时间. 题目大意: ...

  8. HDU 1429 胜利大逃亡(续) (BFS+位压缩)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1429 胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)  ...

  9. hdu 1272 小希的迷宫

    Problem Description 上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走.但是她设计迷宫的思路不一样,首先她认为所有的通道都应该 ...

最新文章

  1. python数据分析(九)-点积与线性代数
  2. asp.net代码审计起始篇之系统搭建
  3. .net aes加密视频等文件
  4. SQL Server 2016 JSON原生支持实例说明
  5. 计算机沟通方式,雅思阅读练习:计算机改变沟通方式
  6. windows下配置caffe-matlab接口
  7. php curl post登录与带cookie模拟登录随笔
  8. TTS Service Extended (进程:com.google.tts)意外停止 恢复被阉割的TTS文字转语音功能
  9. 熟悉JDK8新特性,“Lambda表达式与函数式接口”
  10. 258. Move 0s To The End I -- Laicode
  11. matlab中适应度函数怎么编写,matlab常用的几个适应度评价函数
  12. 物理模拟重力 斜抛运动计算 抛物线计算
  13. 服务器w7系统怎么开启端口,win7如何打开21端口|win7开启21端口的方法
  14. 子网掩码及其与IP地址、网关的关系
  15. java中线,使用Voronoi图查找多边形的中线
  16. 红利逐渐消失殆尽的互联网下半场,前路何方?
  17. java 获取浏览器名称及版本号
  18. GitOps 与 ChatOps 的落地实践
  19. Python之Datasets库安装报错的解决方法
  20. 【uni-app框架介绍及环境配置】

热门文章

  1. QEMU的基本使用方法(MIPS)
  2. CentOS7部署Subversion服务器和TortoiseSVN客户端简记
  3. MQ-2烟雾浓度传感器(STM32F103)
  4. 词嵌入矩阵(Word Embeddings)的生成
  5. 智能无纸化办公,方便快捷,DIY也很简单
  6. 樱桃牌-高逼格键盘敲代码贼爽!包邮送你!
  7. 在 Ubuntu 上添加或删除 PPA 存储库
  8. 黑客零基础入门教程,从入门到精通学习路线规划,看完这篇就够了。
  9. python无法启动此程序丢失zlib.dll_关于winserver2012运行c++程序缺少dll的理由
  10. WinImage 8.10注册算法简单分析