这题主要是计算连通子图的个数(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;
}

hdu 4997 Biconnected的更多相关文章

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

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

  2. HDU 4342——History repeat itself——————【数学规律】

    History repeat itself Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. O ...

  3. HDOJ 2111. Saving HDU 贪心 结构体排序

    Saving HDU Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  4. 【HDU 3037】Saving Beans Lucas定理模板

    http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...

  5. hdu 4859 海岸线 Bestcoder Round 1

    http://acm.hdu.edu.cn/showproblem.php?pid=4859 题目大意: 在一个矩形周围都是海,这个矩形中有陆地,深海和浅海.浅海是可以填成陆地的. 求最多有多少条方格 ...

  6. HDU 4569 Special equations(取模)

    Special equations Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u S ...

  7. HDU 4006The kth great number(K大数 +小顶堆)

    The kth great number Time Limit:1000MS     Memory Limit:65768KB     64bit IO Format:%I64d & %I64 ...

  8. HDU 1796How many integers can you find(容斥原理)

    How many integers can you find Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%I64d ...

  9. hdu 4481 Time travel(高斯求期望)(转)

    (转)http://blog.csdn.net/u013081425/article/details/39240021 http://acm.hdu.edu.cn/showproblem.php?pi ...

随机推荐

  1. HDU 1257(最小拦截系统)

    Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不 能超过前一发的高度.某天,雷达 ...

  2. [WebServer] Windows下Apache与Tomcat的整合

    转自:http://bbs.blueidea.com/thread-2873268-1-1.html 准备工作:1. Apache 2.2.4下载地址:http://cztele1.skycn.com ...

  3. 什么是CAS?

    CAS(Compare-and-Swap),即比较并替换,是一种实现并发算法时常用到的技术,Java并发包中的很多类都使用了CAS技术.CAS需要有3个操作数:内存地址V,旧的预期值A,即将要更新的目 ...

  4. BZOJ 1041 数学

    思路: $x^2+y^2=r^2$$y=\sqrt{(r+x)(r-x)}$令$ d=gcd(r+x,r-x)$设A=$(r-x)/d$ $B=(r+x)/d$则$gcd(A,B)=1$$y^2=d^ ...

  5. webpack-1

    1.webpack 安装新项目npm install --save-dev webpack如果版本较老,在package,json中找到版本号,修改成你要的版本号,在删除node-model文件夹,执 ...

  6. WordPress浏览次数统计插件:WP-Postviews使用

    WP-Postviews使用 1.要让你的博客在页面上显示浏览次数,你需要修改你博客当前使用的主题,在主循环中插入以下代码: 1 <?php if(function_exists('the_vi ...

  7. Kettle通用数据贴源作业设计

    本设计基于以下需求提出 1. 快速接入数据源表(贴源/落地) 2. 无须给单独表开发转换/作业 3. 动态生成数据源连接, 表字段等信息(预先保存在数据仓库中) 本设计所需条件 1. 数据源为关系型数 ...

  8. MyEclipse 中的一些快捷键

    @import url(/css/cuteeditor.css); ------------------------------------- MyEclipse 快捷键1(CTRL) ------- ...

  9. 找回消失的ubuntu启动选项

    启动菜单消失不是第一次了,这一次还是记录下来吧 原文链接:http://blog.chinaunix.net/uid-26527046-id-3748986.html 在安装windows后安装的ub ...

  10. 安装mysql-python的遇到的问题

    最近更新环境后遇到安装mysql-python的问题,感觉挺折腾的,记录一下. 安装mysql-python的时候一直提示下面的错误 _mysql.c() : fatal error C1083: C ...