题意:有一张无重边的无向图, 求有多少个边集,使得删掉边集里的边后,图里恰好有K个连通块。

1≤T≤20
1≤K≤N≤14
0≤M≤N∗(N+1)/2
1≤a,b≤N

思路:From http://blog.csdn.net/di4covery/article/details/51699544

一个简单的结论:删除边集的个数 = 选择边集的个数 , 这样我们就可以把问题转化为选取若干条边使得图里面恰好有K个联通块。

问题可以转化成三个状态压缩DP来完成(这三个DP都不难)

1、num[ mask ] 表示选取mask状态的点两两连边的边数。(这是一个很小的数)

这个数组我们通过状态压缩DP来求

令 u = lowbit (mask)  (即mask状态中编号最小的那个点)

枚举mask中的点v,计算边u,v的个数tmp

num [ mask ] = num [ mask ^u ] + tmp;

2、f [ mask ] 表示选取mask状态的点 ,构成一个联通块 的方案数

同样,利用上一次求出来的num数组,状态压缩DP来求

容斥原理 : 合法方案数 = 总方案数 - 不合法方案数

总方案数 :  2 ^ num( mask ) (每条边选或者不选)

不合法方案数 = tmp:

令 u = lowbit (mask)

枚举mask一个不包含u的子集s,tmp = tmp + f(mask ^ s) * ( 2 ^ num[ s ] );

上面的式子可以理解为枚举一个包含u的联通块,然后剩下的点两两之间的边选或者不选,这些边不会连接之前的联通块

f [ mask ] = 2 ^ num( mask) - tmp;

3、F[ mask ] [ n ]表示选取mask状态的点,构成n个联通块的方案数

实际上 f[ mask ]是 F[mask][1] ,剩下的状态压缩DP相对简单

枚举mask,枚举n

令u = lowbit( mask ),枚举mask一个不包含u的子集s

F[ mask ][ n ] = F[ s ][ n-1 ] * F[ mask ^ s ][ 1 ]

上面的式子等价于F[ mask ][ n ] = F [ s ][ n-1 ] * f[ mask ^ s ]

答案即为F[ mask ] [ n ] (mask为所有点都选择的状态,就是2^n - 1)

Pascal对拍已A,卡常没办法,估计如果去年现场做要跪(现在也跪)

 const mo=;
var g:array[..,..]of int64;
f:array[..]of int64;
two:array[..]of int64;
num:array[..]of longint;
a:array[..,..]of longint;
cas,v,i,t,x,y,sta,max,k1,n,m,j:longint;
tmp:int64; function lowbit(x:longint):longint;
begin
exit(x and (-x));
end; begin
assign(input,'hdoj5713.in'); reset(input);
assign(output,'hdoj5713.out'); rewrite(output);
readln(cas);
two[]:=;
for i:= to do two[i]:=two[i-]* mod mo;
for v:= to cas do
begin
readln(n,m,k1); max:=(<<n)-;
for i:= to n do
for j:= to n do a[i,j]:=;
for i:= to max do
begin
num[i]:=; f[i]:=;
end;
for i:= to max do
for j:= to n do g[i,j]:=;
for i:= to m do
begin
read(x,y);
a[x,y]:=; a[y,x]:=;
end;
for i:= to max do
begin
x:=lowbit(i); y:=round(ln(x)/ln())+;
num[i]:=num[i xor x];
for j:= to n do
if i and (<<(j-))> then num[i]:=(num[i]+a[y,j]) mod mo;
end;
for sta:= to max do
begin
x:=lowbit(sta);
t:=sta xor x; y:=t; tmp:=;
while t> do
begin
tmp:=tmp+f[sta xor t]*two[num[t]];
tmp:=tmp mod mo;
t:=y and (t-);
end;
f[sta]:=(two[num[sta]]-tmp) mod mo;
end;
for i:= to max do g[i,]:=f[i];
for sta:= to max do
for i:= to k1 do
begin
x:=lowbit(sta);
t:=sta xor x; y:=t;
while t> do
begin
g[sta,i]:=g[sta,i]+g[t,i-]*f[sta xor t];
g[sta,i]:=g[sta,i] mod mo;
t:=y and (t-);
end; end; writeln('Case #',v,':');
writeln(g[max,k1]);
end; close(input);
close(output);
end.

对拍用的C++ 1000+MS

 #include <iostream>
#include <cstdio>
#include <cstring>
#define MAXMASK 65537
#define N 20
#define mod 1000000009LL using namespace std; int e[N][N],n,m,k,MASK,num[MAXMASK];
long long F[MAXMASK][N],f[MAXMASK]; inline int lowbit(int x){return x & (-x);}; int edge(int s, int p) {
int ans = ;
for (int i = ; i <= n; i++)
if ((<<(i-)) == p) {p = i;break;}
for (int i = ; i <= n; i++) if ((<<(i-))&s) ans += e[i][p];
return ans;
} int main()
{
freopen("hdoj5713.in","r",stdin);
freopen("right.out","w",stdout);
int T = ;
scanf("%d",&T);
for (int rank=;rank<=T;rank++)
{
memset(e,,sizeof(e));
memset(F,,sizeof(F));
memset(f,,sizeof(f));
memset(num,,sizeof(num));
scanf("%d%d%d",&n,&m,&k);
MASK = ( << n) - ;
for (int i=;i<=m;i++) {
int a,b;
scanf("%d%d",&a,&b);
e[a][b] = e[b][a] = ;//顺带处理自环:)
}
//计算mask状态下的边数
for (int i=;i<=MASK;i++) {
int t = lowbit(i);
num[i] = num[i^t] + edge(i,t);//往状态里新增加一个点
} //状态压缩DP求小f for (int s=;s<=MASK;s++){
int t = lowbit(s);
long long tmp = 0LL;
for (int i=(s^t);i>;i=((i-)&(s^t))) {
tmp += f[s^i] * 1LL*(1LL << num[i]);
tmp %= mod;
}
f[s] = (1LL*(1LL<<num[s]) - tmp) % mod;
}
// for (int s=1;s<=MASK;s++) printf("%d\n",f[s]);
//小f为大F的第一项
for (int s=;s<=MASK;s++) F[s][] = f[s]; //状态压缩DP求大F
for (int s=;s<=MASK;s++)
for (int i=;i<=k;i++) {
int t = lowbit(s);
for (int j=s^t;j>;j=(j-)&(s^t)) {//枚举s的子集
F[s][i] += F[j][i-] * f[s^j];
F[s][i] %= mod;
}
} //防止答案小于0
while (F[MASK][k] < ) F[MASK][k] += mod;
printf("Case #%d:\n%I64d\n", rank, F[MASK][k]);
}
return ;
}

【HDOJ5713】K个联通块(状压DP,计数)的更多相关文章

  1. tyvj2054 四叶草魔杖——连通块 & 状压DP

    题目:http://www.joyoi.cn/problem/tyvj-2054 把点分成几个连通块,和为0的几个点放在一块,在块内跑最小生成树作为这个块的代价: 然后状压DP,组成全集的最小代价就是 ...

  2. 【BZOJ1688】[Usaco2005 Open]Disease Manangement 疾病管理 状压DP

    [BZOJ1688][Usaco2005 Open]Disease Manangement 疾病管理 Description Alas! A set of D (1 <= D <= 15) ...

  3. [luoguP1896] [SCOI2005]互不侵犯King(状压DP)

    传送门 先预处理出来一行中放置国王的所有情况和每种情况所用的国王个数. f[i][j][k]表示前i行放j个国王且最后一行的状态为k的方案数 状压DP即可 #include <cstdio> ...

  4. Codeforces Gym 100610 Problem K. Kitchen Robot 状压DP

    Problem K. Kitchen Robot Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/10061 ...

  5. K - Painful Bases 状压dp

    Painful Bases LightOJ - 1021 这个题目一开始看,感觉有点像数位dp,但是因为是最多有16进制,因为限制了每一个数字都不同最多就有16个数. 所以可以用状压dp,看网上题解是 ...

  6. [WC2008]游览计划(状压dp)

    题面太鬼畜不粘了. 题意就是给一张n*m的网格图,每个点有点权,有k个关键点,让你把这k个关键点连成一个联通快的最小代价. 题解 这题nmk都非常小,解法肯定是状压,比较一般的解法插头dp,但不太好写 ...

  7. 状压dp专题复习

    状压dp专题复习 (有些题过于水,我直接跳了) 技巧总结 : 1.矩阵状压上一行的选择情况 \(n * 2^n\) D [BZOJ2734][HNOI2012]集合选数 蒻得不行的我觉得这是一道比较难 ...

  8. 状压DP小拼盘

    有的DP题,某一部分的状态只有两种,选或不选. 开数组记录,代价太大,转移不方便. 状态压缩意为,用 “0/1“ 表示 “选/不选“ . 把状态表示为二进制整数. There are 10 kinds ...

  9. 【BZOJ1725】[Usaco2006 Nov]Corn Fields牧场的安排 状压DP

    [BZOJ1725][Usaco2006 Nov]Corn Fields牧场的安排 Description Farmer John新买了一块长方形的牧场,这块牧场被划分成M列N行(1<=M< ...

随机推荐

  1. 窗口Dialog

    Dialog是窗口的意思,它是Window的子类.与frame相比,frame是我们大的窗口,而dialog便是那种弹出来和你说话的对话框. Dialog类的默认布局是BorderLayout Dia ...

  2. 转】R利剑NoSQL系列文章 之 Hive

    原博文出自于: http://blog.fens.me/category/%E6%95%B0%E6%8D%AE%E5%BA%93/page/3/ 感谢! Posted: Jul 27, 2013 Ta ...

  3. WAMP配置虚拟目录

    1.启动wamp所有服务,输入localhost或localhost:端口号确保wamp环境正常无误. 2.设置httpd.conf 2.1打开文件:单击wamp在电脑右下角的图标=>wamp= ...

  4. AJPFX关于Collection 集合的表述

    集合的遍历class Demo_Collection{     public static void main(String[] args){          Collection c = new ...

  5. AJPFX总结JAVA基本数据类型

    1:关键字(掌握)        (1)被Java语言赋予特定含义的单词        (2)特点:                全部小写.        (3)注意事项:              ...

  6. AJPFX总结正则表达式的概述和简单使用

    正则表达式的概述和简单使用* A:正则表达式        * 是指一个用来描述或者匹配一系列符合某个语法规则的字符串的单个字符串.其实就是一种规则.有自己特殊的应用.        * 作用:比如注 ...

  7. 使用Jquery1.9 版本 来实现全选

    在使用Jquery实现全选以及反选的时候, 使用attr()实现的时候,在浏览器第一次运行可以全选,但是第二次再全选,不管用.  通过查找资料,用 prop()方法代替attr()方法就行了. 注意: ...

  8. Android开发——蓝牙

    ---恢复内容开始--- 前言 孤芳自赏,一揽芳华: 人情冷暖,自在人心: 登高远眺,望步止前: 喜笑言开,欺人骗己. 上篇文章介绍了基本的蓝牙使用,书写的demo也不是很完善,希望各位大神能够改正. ...

  9. ERROR 1 (HY000): Can't create/write to file '/tmp/#sql_830_0.MYI' (Errcode: 13)

    mysql操作时,出现报错. 执行describe 命令时, 临时文件目录没有创建或者无写入权限:于是: cd /var/lib/mysql/ #进入mysql数据目录 mkdir tmp #创建需要 ...

  10. uoj #15. 【NOIP2014】生活大爆炸版石头剪刀布

    石头剪刀布是常见的猜拳游戏:石头胜剪刀,剪刀胜布,布胜石头.如果两个人出拳一 样,则不分胜负.在<生活大爆炸>第二季第 8 集中出现了一种石头剪刀布的升级版游戏. 升级版游戏在传统的石头剪 ...