ssoj1027树形图计数count(状压dp)
2015-09-12 17:00
211 查看
题目描述
小k同学最近正在研究最小树形图问题。所谓树形图,是指有向图的一棵有根的生成树,其中树的每一条边的指向恰好都是从根指向叶结点的方向。现在小k在纸上画了一个图,他想让你帮忙数一下这个图有多少棵树形图。输入
第1行输入1个正整数:n,表示图中点的个数第2~n+1行每行输入n个字符,描述了这个图的邻接矩阵。第i+1行第j个字符如果是0则表示没有从i连向j的有向边,1表示有一条从i到j的有向边。
输出
输出1行1个整数,表示这个有向图的树形图个数。样例输入
40100001000011000样例输出
4提示
【数据范围】对于100%的数据,n<=8。
#include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <algorithm> #include <cmath> #define ll long long using namespace std; const int maxn=1<<(9); ll f[11][maxn],ans=0,cnt; int n,a[11][11],mx; char s[11]; int main(){ scanf("%d",&n); for(int i=1;i<=n;++i){ scanf("%s",s); for(int j=1;j<=n;++j)a[i][j]=s[j-1]-48; } mx=1<<n; for(int i=1;i<=n;++i)f[i][1<<(i-1)]=1; for(int j=1;j<mx;++j){ for(int i=1;i<=n;++i)if((j>>(i-1))&1){ for(int x=1;x<j;++x)if((x|j)==j){ for(int k=1;k<=n;++k)if((k!=i) && (((j^x)>>(k-1))&1)){ cnt=0; for(int t=1;t<=n;++t)if(((x>>(t-1))&1) && a[t][k])++cnt; f[i][j]+=cnt*f[k][j^x]*f[i][x]; } } cnt=0; for(int t=1;t<=n;++t)if((j>>(t-1))&1)++cnt; if(cnt-1)f[i][j]/=cnt-1; } } for(int i=1;i<=n;++i)ans+=f[i][mx-1]; printf("%lld\n",ans); return 0; }
思路:f[ i ][ j ]指以i为结点,状态为j的树形图数目。f[ i ][ j ]可以由两个树形图合并而来,即f[i][j]+=cnt*f[k][j^x]*f[i][x],
其中cnt为两棵树的连接方式。最后我们会发现对于每个结点都算了sum(状态中的结点数-1(树根自己要减掉))次,因此要除去。
相关文章推荐
- C++中智能指针的设计和使用
- 返回指针值的函数(2)
- 机器学习中的决策树及其演化算法
- HDU 5375 Gray code
- 欢迎使用CSDN-markdown编辑器
- 返回指针值的函数(2)
- Java 基本数据类型
- Prepared for New Acmer
- 第十二篇:OC中的对象内存管理都是对 对象引用计数器 进行管理
- 短信(会话)删除(转)
- 坚持
- Java 驼峰与下划线的属性名互相转换
- Notification使用以及PendingIntent.getActivity() (转)
- opencv在ios上的开发教程
- iGriamceV8.0 IG8.0.0 iOS8 V8基本设置和使用教程图
- HDU 1114 Piggy-Bank 【完全背包】
- 网络安全和机器学习:准确的特征可通向成功
- Linux httpd 跳转简单方法二
- POJ 2954-Triangle(计算几何+皮克定理)
- C#调用Excel VBA宏