题目:http://acm.hdu.edu.cn/showproblem.php?pid=5304

16个点的无向图,问能生成多少个n条边的连通图。(即多一条边的树)

先n^3 * 2^n 枚举全部的环。状压dp即可。dp[i][j]表示以i为终点,走了j状态集合的方案数。要枚举起点,每次走比起点大的点。所以要n^3 2^n枚举。

把环压缩成点。构造基尔霍夫矩阵。每种状态下n^3求生成树。

故总复杂度是 n^3 * 2^n + n^3 * 2^n

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
typedef long long ll;
const ll mod = 998244353;
const int N = (1<<16)+10;
ll ans;
int f[N],dp[20][N];
bool d[20][20];
int n,m; ll exgcd(ll a,ll b,ll &x,ll &y)//乘法逆元返回的d是a,b的公约数。x是a mod b的逆元
{
if(b==0)
{
x=1ll;y=0;
return a;
}
ll d=exgcd(b,a%b,x,y);
ll t=x;
x=y;
y=t-a/b*y;
return d;
} ll Gauss(int C[][20],int n)//计算n阶行列式的绝对值 % mod
{
ll ans=1ll;
int flag=1;//行列交换的次数
int i,j,k;
for(i=0;i<n;i++)
{
if(C[i][i]==0)
{
for(j=i+1;j<n;j++)
if(C[j][i])break;
if(j==n)return 0;//某列的值全是0的ans=0。
flag=!flag;
for(int k=i;k<n;k++)
swap(C[i][k],C[j][k]);//i和j行交换
}
ans=ans*C[i][i]%mod;//对角线相乘
ll x,y;
int tp=exgcd(C[i][i],mod,x,y);//x为逆元 for(k=i+1;k<n;k++)
C[i][k]=C[i][k]*x%mod; for(int j=i+1;j<n;j++)
for(int k=i+1;k<n;k++)
{
C[j][k]=(C[j][k]-(ll)C[j][i]*C[i][k])%mod;
if(j==k)
C[j][k]=(C[j][k]+mod)%mod;
}
for(k=i+1;k<n;k++)
C[i][k]=(ll)C[i][k]*C[i][i]%mod; } ans=(ans%mod+mod)%mod;
if(flag) return ans;
else return mod-ans;
} ll solve(int s){
int Kir[20][20];
int vis[20],col[20];
memset(Kir,0,sizeof(Kir));
memset(vis,0,sizeof(vis));
memset(col,-1,sizeof(col));
for(int i=0;i<n;i++)
if((1<<i)&s) vis[i]=1;
int num=0;
for(int i=0;i<n;i++)if(!vis[i])
col[i]=num++;
for(int i=0;i<n;i++)if(vis[i])
col[i]=num;
num++; for(int i=0;i<n;i++)
for(int j=0;j<n;j++)if(i!=j && col[i]!=col[j])
Kir[col[i]][col[j]] -= d[i][j];
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)if(col[i]!=col[j])
Kir[col[i]][col[i]] += d[i][j]; return Gauss(Kir,num-1);
} int main(){
// freopen("e.in","r",stdin);
// freopen("my05.out","w",stdout);
while(scanf("%d%d",&n,&m)!=EOF){
ans = 0;
memset(d,0,sizeof(d));
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
u--,v--;
d[u][v] = d[v][u] = 1;
} memset(f,0,sizeof(f));
for(int st=0;st<n;st++){
memset(dp,0,sizeof(dp));
dp[st][(1<<st)] = 1;
for(int s=1;s<(1<<n);s++)if((1<<st)&s){
for(int i=0;i<n;i++)if(i>=st)
if(dp[i][s]){
for(int j=st+1;j<n;j++)
if( (s&(1<<j))==0 && d[i][j] )
dp[j][s|(1<<j)] = ( dp[i][s] + dp[j][s|(1<<j)])%mod;
if(d[i][st])
f[s] = ( dp[i][s] + f[s] )%mod;
}
}
} ll inv2 = (mod+1)/2;
for(int i=1;i<(1<<n);i++){
if(f[i]){
int co = 0;
for(int j=0;j<n;j++)if((1<<j)&i) co++;
if(co<=2) continue;
f[i] = ((ll)f[i]*inv2)%mod;
ans = (ans + (ll)f[i]*solve(i)%mod )%mod;
}
} printf("%I64d\n",ans); } return 0;
}

hdu5304 Eastest Magical Day Seep Group&#39;s Summer 状压dp+生成树的更多相关文章

  1. HDU 5304(Eastest Magical Day Seep Group&#39;s Summer-环加外向树生成树计数)[Template:Kirchhoff矩阵]

    Eastest Magical Day Seep Group's Summer Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 655 ...

  2. uva 11825 Hackers&#39; Crackdown (状压dp,子集枚举)

    题目链接:uva 11825 题意: 你是一个黑客,侵入了n台计算机(每台计算机有同样的n种服务),对每台计算机,你能够选择终止一项服务,则他与其相邻的这项服务都终止.你的目标是让很多其它的服务瘫痪( ...

  3. 状压dp Mondriaan&#39;s Dream poj2411

    超经典的一道题目,实现这题的方法也有非常多种 1.利用DFS建立矩阵,然后通过高速矩阵幂得到答案(运用于min(m,n)比較小.可是max(m,n)很大的情况) 2.利用dp状压解决 第一种在我的还有 ...

  4. group:状压dp,轮廓线

    神仙题.但是难得的傻孩子cbx没有喊题解,所以也就难得的自己想出来了一个如此神仙的题. 如果是自己想的,说它神仙是不是有点不合适啊..? 反正的确不好像.关键就在于这个标签.颓完标签就差不多会了. % ...

  5. group 状压dp

    应某些人要求,我把标签删掉了 这是一道好题. 一看$c<=16$果断状压,但是怎么压? 一个很显然的思路是,枚举上下两层的状态,每一层的状态极限有$C(c,c/2)$,c=16的时候有13000 ...

  6. [杂题]:group(状压DP+轮廓线)

    题目描述 $pure$在玩一个战略类游戏.现在有一个士兵方阵,每行有若干士兵,每个士兵属于某个兵种.行的顺序不可改变,且每一行中士兵的顺序也不可改变.但由于每一行都有$C$个位置($C$不小于任一行的 ...

  7. [生产环境数据恢复]innobackupex: fatal error: OR no &#39;datadir&#39; option in group &#39;mysqld&#39; in MySQL options

    1 运行恢复命令  [xxx@xxx-c001db1 tmp]$ time /usr/bin/innobackupex --rsync --user="user" --passwo ...

  8. hdu 4638 Group(离线+树状数组)

    Group Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Subm ...

  9. UVA 1484 - Alice and Bob&#39;s Trip(树形DP)

    题目链接:1484 - Alice and Bob's Trip 题意:BOB和ALICE这对狗男女在一颗树上走,BOB先走,BOB要尽量使得总路径权和大,ALICE要小,可是有个条件,就是路径权值总 ...

随机推荐

  1. js 根据身份证号获取性别,年龄,等

    $(function(){        $("#corpOwnerIdno").blur(function(){          //获取输入身份证号码             ...

  2. 初识Redux-Saga

    Redus-saga是一个redux的中间件,主要用来简便而优雅的处理redux应用里的副作用(side effect相对于pure function这类概念而言的).它之所以可以做到这一点主要是使用 ...

  3. redis特性 存储 API 集群 等

    公司组内技术分享,刚好最近工作用redis构建缓存,所以想同事们分享关于redis的一些知识, 这些知识不仅仅是包括一些API层,而是一些关于redis功能功能特性的 目前为什么使用redis构建缓存 ...

  4. WPF中DataGrid垂直滚动条滚动后导致每行CheckBox选择错乱

    问题: WPF的DataGrid中出现选取或者多选以及单选的时候,出现滚动条的时候,如果发生了滚动,默认情况下就会出现已经选择的CheckBox错乱.这样的原因何在? 解决方案: 经过查阅资料,了解到 ...

  5. Maven启动Java Web工程,8081和8086端口号被占用

    Maven启动Java Web工程, <!-- 配置tomcat插件 --> <build> <plugins> <plugin> <groupI ...

  6. 关于tolua的使用

    一.首先在引擎的跟目录下找到cocos2d-x自带的工具tolua++ 二.使用tolua++生成自定义类的声明 打开tool文件夹中的readme文件如下: 1. Generating the lu ...

  7. java中的static和final关键字

    一:static 1)修饰成员变量: static关键字可以修饰成员变量,它所修饰的成员变量不属于对象的数据结构,而是属于类的变量,通常通过类名来引用static成员. 当创建对象后,成员变量是存储在 ...

  8. Azure cli使用arm创建多网卡虚拟机

    登录 Azure CLI 并使用 Resource Manager 模式: azure config mode arm 在以下示例中,请将示例参数名称替换为你自己的值.示例参数名称包括 myResou ...

  9. MySQL修改表

    一.给表mytablename添加新字段newcolumn alter table mytablename add newcolumn varchar(50) COMMENT '新字段备注信息' 二. ...

  10. JS 判断某个字符串是否存在与数组中

    <script> function in_array(stringToSearch, arrayToSearch) { for (s = 0; s < arrayToSearch.l ...