[日常训练] 树形图计数
来源:互联网 发布:html input value js 编辑:程序博客网 时间:2024/05/17 07:54
【问题描述】
小k同学最近正在研究最小树形图问题。所谓树形图,是指有向图的一棵有根的生成树,其中树的每一条边的指向恰好都是从根指向叶结点的方向。现在小k在纸上画了一个图,他想让你帮忙数一下这个图有多少棵树形图,树形图必须包括所有点。
【输入格式】
第1行输入1个正整数:n,表示图中点的个数
第2~n+1行每行输入n个字符,描述了这个图的邻接矩阵。第i+1行第j个字符如果是0则表示没有从i连向j的有向边,1表示有一条从i到j的有向边。
【输出格式】
输出1行1个整数,表示这个有向图的树形图个数。
【输入输出样例】
count.in
4
0100
0010
0001
1000
count.out
4
【数据范围】
对于50%的数据,n<=4。
对于100%的数据,n<=8。
【分析】
- 首先看到数据范围
n≤8 想到搜索 - 因为子节点有多个,每次搜索子节点显然是很难实现的,我们考虑搜索每个节点的父节点
- 若节点
y 能够成为节点x 的父节点,它必然要满足两个条件:
[1]、存在边y→x
[2]、当前y 不为x 的子孙 - 对于条件[1],我们可以直接反着建边(
x→y ),则搜索时就能很方便地访问到节点y - 对于条件[2],我们记
sum[x] 表示一个二进制数,若第i 位上为1,i 为x 的子孙,则y 就要满足sum[x] &2y=0 。 - 那么当我们在当前的树上连边
y→x 时,x 及x 的子孙都要算入y 及y 的祖先的sum 中,同理:回溯时,x 及x 的子孙都要从y 及y 的祖先的sum 中扣除,两者可用位运算中的或和异或实现。
【代码】
#include <iostream>#include <cstdio>using namespace std;const int N = 10, M = 100;int fa[N], sum[N], n, x, Ans;struct Edge{ int to; Edge *nxt;}p[M], *T = p, *lst[N];inline void addEdge(const int &x, const int &y){ (++T)->nxt = lst[x]; lst[x] = T; T->to = y;} inline void Dfs(const int &x, const int &rt){ int y, w; if (x == rt) Dfs(x + 1, rt); if (x > n) return (void)(++Ans); for (Edge *e = lst[x]; e; e = e->nxt) { y = e->to; if (sum[x] & (1 << y)) continue; fa[x] = w = y; int tmp = sum[x] | (1 << x); while (w) sum[w] |= tmp, w = fa[w]; Dfs(x + 1, rt); fa[x] = 0; w = y; while (w) sum[w] ^= tmp, w = fa[w]; }}int main(){ freopen("count.in", "r", stdin); freopen("count.out", "w", stdout); scanf("%d", &n); for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j) { scanf("%1d", &x); if (x) addEdge(j, i); } for (int i = 1; i <= n; ++i) Dfs(1, i); printf("%d\n", Ans); fclose(stdin); fclose(stdout); return 0;}
阅读全文
1 0
- [日常训练] 树形图计数
- superoj922 树形图计数
- 树形图计数
- 【ssoj1027】树形图计数
- 树形图计数 count题解
- 周六日常训练,背包dp,树形dp,简单dp以及很多数学?
- HEU日常训练10.02
- 日常训练小结
- 日常训练20161012 道路网
- 日常训练20161012 醉酒
- 日常训练20161014 跟踪
- 日常训练20161018 证据
- 日常训练20161018 subset
- 日常训练 平均数
- 日常训练 水箱
- 日常训练 棋盘游走
- 日常训练 20170531 数字
- 日常训练 20170531 探险
- 关于http url中特殊符号的记录
- 集合复习
- [译]The Python Tutorial#2. Using the Python Interpreter
- ioctl的cmd不能为2
- POJ 2385 Apple Catching(牛吃苹果)
- [日常训练] 树形图计数
- 剑指offer面试题60 把二叉树打印成多行(Java实现)
- java基础的一些理解
- updateByPrimaryKey和updateByPrimaryKeySelective insert和insertSelective
- bzoj2141[排队]
- MyEclipse 配置
- linux-2.6.11-exec
- robots协议
- java登录验证码(框架版)