这题主要是计算连通子图的个数(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. layer获取弹出frame层数据

    通常,弹出层关闭之前,需要将部分数据传入父页面.这个时候怎么办呢? 通过success获取frame层的index. 然后通过cancel事件,获取子页面数据. 拿获取高德地图坐标为例: // 显示地 ...

  2. BZOJ-4706 B君的多边形 OEIS

    题面 题意:有一个正n多边形,我们要连接一些对角线,把这个多边形分成若干个区域,要求连接的对角线不能相交,每个点可以连出也可以不连出对角线,即最终不要求所有区域均为三角形,问总方案数mod (10^9 ...

  3. SQLServer 表连接时使用top 1 去除重复数据

    left join SM_SOLine soline on soline.SO=so.ID and soline.DocLineNo=(select MAX(DocLineNo) from SM_SO ...

  4. layui新手使用

    1,首先最重要的是引入官方的layui.js  layui.css文件 2,在自己的项目中新建一个目录 再在该目录下建一个js文件,js中写入 layui.define(['layer', 'form ...

  5. Javassist介绍

    要想将编译时不存在的类在运行时动态创建并加载,通常有两种策略: 1. 动态编译 2. 动态生成二进制字节码(.class) 对于第二种策略,实际上已经有诸多比较成熟的开源项目提供支持,如CGLib.A ...

  6. Laravel5 开启Debug

    Laravel默认没有开启Debug,打开需要两步: .env文件中设置APP_DEBUG=true: 把Laravel服务重启一下(摸索出来的). 这只是开启了基本的调试模式,如果需要看更详细的调试 ...

  7. ACM___数学___九的余数

    九的余数 时间限制:3000 ms  |            内存限制:65535 KB 难度:3   描述  现在给你一个自然数n,它的位数小于等于一百万,现在你要做的就是求出这个数整除九之后的余 ...

  8. 资深程序员总结:彻底理解Spring容器和应用上下文

    点关注,不迷路:持续更新Java架构相关技术及资讯热文!!! 有了Spring之后,通过依赖注入的方式,我们的业务代码不用自己管理关联对象的生命周期.业务代码只需要按照业务本身的流程,走啊走啊,走到哪 ...

  9. 手动实现aop编程

    手动实现aop编程(运用代理模式实现) aop:aspect object programming 功能:让关注点与业务代码分离 关注点:重复代码就叫做关注点 切面:关注点形成的类,就叫切面(类) 面 ...

  10. 网站出现502 bad getway

    最近项目之余,领导叫解决下系统网站经常出现502的问题,作为小头头的我,怎能不顶上. 流程开始走起,先查nginx,嗯,配置是大众的.是不是缓存溢出了呢.调节buffer的值 .貌似也没什么影响啊.5 ...