hdu 4997 Biconnected
这题主要是计算连通子图的个数(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的更多相关文章
- HDU 4997 Biconnected (状态压缩DP)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4997 题意:一个n个点的完全图中去掉一些边.求这个图有多少个子图是边双联通的.(就是去掉任意一条边之后 ...
- HDU 4342——History repeat itself——————【数学规律】
History repeat itself Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. O ...
- HDOJ 2111. Saving HDU 贪心 结构体排序
Saving HDU Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- 【HDU 3037】Saving Beans Lucas定理模板
http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...
- hdu 4859 海岸线 Bestcoder Round 1
http://acm.hdu.edu.cn/showproblem.php?pid=4859 题目大意: 在一个矩形周围都是海,这个矩形中有陆地,深海和浅海.浅海是可以填成陆地的. 求最多有多少条方格 ...
- HDU 4569 Special equations(取模)
Special equations Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u S ...
- HDU 4006The kth great number(K大数 +小顶堆)
The kth great number Time Limit:1000MS Memory Limit:65768KB 64bit IO Format:%I64d & %I64 ...
- HDU 1796How many integers can you find(容斥原理)
How many integers can you find Time Limit:5000MS Memory Limit:32768KB 64bit IO Format:%I64d ...
- hdu 4481 Time travel(高斯求期望)(转)
(转)http://blog.csdn.net/u013081425/article/details/39240021 http://acm.hdu.edu.cn/showproblem.php?pi ...
随机推荐
- 康少带你玩转JavaScript
目录 1.JavaScript简述 2.JavaScript引入方式 3.JavaScript语法基础 4.JavaScript数据类型 5.运算符 6.流程控制 7.函数 8.内置对象和方法 1.J ...
- MySQL架构与SQL执行流程
MySQL架构设计 下面是一张MySQL的架构图: 上方各个组件的含义如下: Connectors 指的是不同语言中与SQL的交互 Management Serveices & Utiliti ...
- DevExpress的GridControl拖拽DraopDown后计算HitInfo的RowHandle错误
最近在使用GridControl的拖拽功能时候遇到了一个问题:当GridControl触发DropDrop事件时,计算对应的RowHandle错误.当把鼠标拖拽到GridView一个单元格的靠上面的部 ...
- Vue-router记录
一.嵌套路由默认选中第一个子路由 可以给主路由加一个重定向的属性,把路径指向相应的子路由. { path: '/home', name: 'Home', //重定向 redirect: '/home/ ...
- BZOJ1096: [ZJOI2007]仓库建设(dp+斜率优化)
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 5790 Solved: 2597[Submit][Status][Discuss] Descript ...
- Android stroke 边框线 某一边
有时候需要给View加边框线,我们经常是四边一起加,就像这样: <shape xmlns:android="http://schemas.android.com/apk/res/and ...
- (转载)Android 方法数超过64k、编译OOM、编译过慢解决方案。
Android 方法数超过64k.编译OOM.编译过慢解决方案. 目前将项目中的leancloud的即时通讯改为环信的即时通讯.当引入easeui的时候 出现方法数超过上限的问题. 搜索一下问题, ...
- 【Oracle】DG中 Switchover 主、备切换
操作系统:OEL 5.6 数据库版本:Oracle11gR2 11.2.0.4.0 Switchover切换要求主库和备库在数据同步情况下进行,是主备之间的正常切换,主要用于日常维护.灾备演练等.切 ...
- swift的计算属性和懒加载
计算属性每次都重新计算. 懒加载只计算一次. 可以借助backing store将计算属性转化为懒加载属性. 计算属性实质上退化为函数调用. 计算属性的标示是get.set.
- paramiko模块学习笔记
SSHClient 基于用户名密码连接 import paramiko # 创建SSH对象 ssh = paramiko.SSHClient() # 允许连接不在know_hosts文件中的主机 ss ...