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 ...
随机推荐
- hdoj-1004-Let the Balloon Rise(水题)
Let the Balloon Rise Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Oth ...
- 使用ssh和putty操控远程的linux server
windows下没有openssh,今天这里使用openssh-server作为server,windows下使用putty作为client, putty主要流程分以下几步: step 1: 下载pu ...
- js 随机生成信用卡号
本文实例讲述了JavaScript随机生成信用卡卡号的方法.分享给大家供大家参考.具体分析如下: 这段JS代码根据信用卡卡号产生规则随机生成信用卡卡号,是可以通过验证的,仅供学习参考,请不要用于非法用 ...
- ASP.NET MVC上传文件 未显示页面,因为请求实体过大。解方案
在Dropzone中设置 maxFilesize: 350, //MB 但上传的文件没有到最大限定350MB,就报出来 未显示页面,因为请求实体过大的错误 Web.config中设置 maxAl ...
- TYVJ 1427 线段树的基本操作
题意: 单点修改,区间最值 思路: 线段树 原题请戳这里 //By SiriusRen #include <cstdio> #include <cstring> #includ ...
- IT业常见职位英语缩写全攻略及详解
现在中国人流行起英文名字,连职位也跟着作秀,什么CEO.COO.CFO.CTO.CIO啦,那CEO.COO.CFO.CTO.CIO到底是什么意思呢?总被这些概念搞晕,这可不是搞IT的应该犯的错误哦,好 ...
- [转]解决C# WinForm 中 VSHOST.EXE 程序不关闭的问题
右击“解决方案”--属性-调试栏-启用调试器部分-“启用Visual studio宿主进程”不勾选
- 【转载】程序猿转型AI必须知道的几件事!
历史上AI火过两次,但是最终都已销声匿迹作为结束.这次AI大火的原因:AlphaGo 4比1战胜李世石,相对于一些外行人的恐慌和恐惧,其实很多业内人员在这场世纪之战结束后,都为人类点上了一个大大的赞. ...
- ubuntu16.04下编译安装OpenCV
一: 预先配置 为使OpenCV的安装在编译时更完备,预先安装好所有的开发平台: 二:编译OpenCV 在OpenCV官网下载UNIX的源码包: 安装一下软件: sudo apt-get instal ...
- (转)基于MVC4+EasyUI的Web开发框架经验总结(8)--实现Office文档的预览
http://www.cnblogs.com/wuhuacong/p/3871991.html 基于MVC4+EasyUI的Web开发框架经验总结(8)--实现Office文档的预览 在博客园很多文章 ...