【ssoj1027】树形图计数
来源:互联网 发布:c 语言英文怎么说 编辑:程序博客网 时间:2024/05/17 08:08
2407: 树形图计数
时间限制: 1 Sec 内存限制: 128 MB题目描述
小 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<cstdio>#include<iostream>#include<algorithm>#include<cmath>#include<cstring>using namespace std;#define MAXN 8#define MAXM#define INF 0x3f3f3f3ftypedef long long int LL;bool G[MAXN+5][MAXN+5];int N;int fa[MAXN+5];int root(int x){return fa[x]==x?x:root(fa[x]);}int dfs(int &rt,int u)//此处是以rt为根,枚举u和谁相连(其中树中边从叶节点向根指){ if(rt==u)return dfs(rt,u+1); if(u>N)return 1; int rn=0; for(int v=1;v<=N;++v) if(G[v][u]&&root(v)!=root(u)) { fa[u]=v; rn+=dfs(rt,u+1); fa[u]=u; } return rn;}int main(){ scanf("%d",&N); int i,j; char s[MAXN+5]; for(i=1;i<=N;++i) { scanf("%s",s+1); for(j=1;j<=N;++j) G[i][j]=s[j]-'0'; fa[i]=i; } int ans=0; for(i=1;i<=N;++i) ans+=dfs(i,1); printf("%d\n",ans);}
除此之外,这道题还可以用状压DP解决。
dp[i][s]表示以i为根,集合中状态为s的构造方案数。
dp[i][s]=dp[i][s0]*dp[j][s^s0]*连边的方案数
但因为dp[i][s]会在转移中重复计算 节点数-1 次,(同一种连边方式可能由不同的节点作为根转移过来)
所以算出dp[i][s]后要除以 节点数-1 。
#include<cstdio>#include<iostream>#include<algorithm>#include<cmath>#include<cstring>using namespace std;#define MAXN 8#define MAXS 256#define INF 0x3f3f3f3ftypedef long long int LL;bool G[MAXN+5][MAXN+5];int N;int dp[MAXN+10][MAXS+100];int main(){ scanf("%d",&N); int i,j; char str[MAXN+5]; for(i=1;i<=N;++i) { scanf("%s",str+1); for(j=1;j<=N;++j) G[i][j]=str[j]-'0'; } for(i=1;i<=N;++i) dp[i][1<<(i-1)]=1; int M=(1<<N)-1; for(int s=1;s<=M;++s) for(i=1;i<=N;++i)if(s&(1<<(i-1))) { for(int s0=1;s0<s;++s0)if((s0|s)==s) for(j=1;j<=N;++j)if(i!=j&&((1<<(j-1))&(s^s0))) { int cnt=0; for(int k=1;k<=N;++k) if(G[k][j]&&(s0&(1<<(k-1))))++cnt; dp[i][s]+=cnt*dp[i][s0]*dp[j][s^s0]; } int cnt=0; for(j=1;j<=N;j++) if(s&(1<<(j-1)))++cnt; if(cnt-1)dp[i][s]/=cnt-1; } int ans=0; for(i=1;i<=N;++i) ans+=dp[i][M]; printf("%d\n",ans);}
2 0
- 【ssoj1027】树形图计数
- ssoj1027树形图计数count(状压dp)
- superoj922 树形图计数
- 树形图计数
- 树形图计数 count题解
- [日常训练] 树形图计数
- [有向图树形图计数] BZOJ 4894 天赋
- 【树形dp】连通块计数
- HDU 4705 Y (树形DP + 计数)
- codeforces round# 302 (div1 D 树形计数)
- SPOJ Con-Junctions(树形dp,方案计数)
- 图计数
- poj 3140 Contestants Division(树形dp? dfs计数+枚举)
- UVA 11174 Stand in a Line 树形dp+计数
- Codeforces 486D Valid Sets 树形dp+计数
- CodeForces 158E Phone Talks 树形dp+计数
- Bzoj2111:[ZJOI2010]Perm 排列计数:树形动态规划+组合数学
- Codeforces 486D Valid Set 树形DP+计数
- 使用maven插件反向映射generatorConfig.xml生成代码
- 浮动( 上机2)
- 获取当前日期
- 详解统计信号处理之 克拉美罗界
- 使用Amazon AWS搭建GPU版tensorflow深度学习环境
- 【ssoj1027】树形图计数
- redis :jedisTemplate中的Zset 存储
- 优雅的页面动态隐藏标签
- javascript常用互动方法
- Windows下PBC的安装
- mysql数据库&表结构
- 不同数据库中的主键自增(Mysql,Oracle,SQL Server,DB2,)
- Android学习之路:AndroidStudio创建EmptyActivity隐藏标题栏
- Java并发编程实战笔记(2)- ConcurrentHashMap