题目传送门

分析

放一个dalao博客: xyz32768 的博客,看完再回来看本蒟蒻的口胡吧(其实嘛…不回来也行)

  • 精髓是合并的方案数的计算,至于为什么是Ci−1j−1\large C_{i-1}^{j-1}Ci−1j−1​,是因为当前点必须独立成为第一部分
  • 时间复杂度的O(n3)O(n^3)O(n3)也是个玄学东西。其实是因为枚举j,kj,kj,k时上限分别是sz[u]sz[u]sz[u](到目前所有子树的大小)和sz[v]sz[v]sz[v](这棵子树的大小),乘起来就是相当于在uuu下方中枚举不同子树内的点对。那么每一对只会在lcalcalca处被枚举到。因为在lcalcalca下方,两个点不可能一起被枚举到;而在lcalcalca上方,它们已经存在于同一子树了。所以这个枚举总时间复杂度是O(n2)O(n^2)O(n2)。最终复杂度就为O(n3)O(n^3)O(n3)
  • 注意判断环的方式有没有考虑周全。因为不能用简单的用入度为000来判断每一棵树的根节点(因为可能有环),我写的naivenaivenaive的O(n)O(n)O(n)的判环各种姿势WAWAWA,见下
  • 第一发

  • 第二发





  • 。。。于是直接O(n2)O(n^2)O(n2)每次清零visvisvis数组跑dfsdfsdfs。能过就行。
  • CODE

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 105;
const int mod = 1e9+7;
int n, m, edgecnt;
struct edge { int u, v; }e[MAXN]; int scc[MAXN];
int find(int x) { return scc[x] == x ? x : scc[x]=find(scc[x]); } int fir[MAXN], to[MAXN], nxt[MAXN], cnt, in[MAXN];
inline void add(int u, int v) { to[++cnt] = v; nxt[cnt] = fir[u]; fir[u] = cnt; in[v]++; } bool vis[MAXN];
bool check(int u) {
if(vis[u]) return 0;
vis[u] = 1;
for(int i = fir[u]; i; i = nxt[i])
if(!check(to[i])) return 0;
return 1;
} int f[MAXN][MAXN], sz[MAXN], tmp[MAXN], c[MAXN][MAXN];
void dp(int u) {
f[u][1] = sz[u] = 1;
for(int l = fir[u], v; l; l = nxt[l]) {
dp(v = to[l]);
for(int i = 1; i <= sz[u]+sz[v]; ++i) tmp[i] = 0;
for(int i = 1; i <= sz[u]+sz[v]; ++i)
for(int j = 1; j <= sz[u] && j <= i; ++j)
for(int k = 1; k <= sz[v] && k <= i; ++k)
if(k + j >= i)
tmp[i] = (tmp[i] + 1ll * f[u][j] * f[v][k] % mod * c[i-1][j-1] % mod * c[j-1][k-(i-j)] % mod) % mod;
for(int i = 1; i <= sz[u]+sz[v]; ++i) f[u][i] = tmp[i];
sz[u] += sz[v];
}
} int main () {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) scc[i] = i;
char s[2];
for(int i = 1, x, y; i <= m; ++i) {
scanf("%d%s%d", &x, s, &y);
if(s[0] == '=') scc[find(y)]=find(x);
else {
if(s[i] == '>') swap(x, y); //emmm... unnecessary
e[++edgecnt] = (edge){ x, y };
}
}
for(int i = 1; i <= n; ++i) find(i);
for(int i = 1; i <= edgecnt; ++i) {
if(scc[e[i].u] == scc[e[i].v]) return puts("0"), 0;
add(scc[e[i].u], scc[e[i].v]);
}
bool flg = 1;
for(int i = 1; i <= n; ++i) if(scc[i] == i) {
memset(vis, 0, sizeof vis);
if(!check(i)) { flg = 0; break; } //judge the circle
if(!in[i]) add(0, i);
}
if(!flg) return puts("0"), 0;
c[0][0] = 1;
for(int i = 1; i <= n; ++i) {
c[i][0] = c[i][i] = 1;
for(int j = 1; j < i; ++j)
c[i][j] = (c[i-1][j-1] + c[i-1][j]) % mod;
}
dp(0);
int ans = 0;
for(int i = 1; i <= sz[0]; ++i)
ans = (ans + f[0][i]) % mod;
printf("%d\n", ans);
}
  • 出于良心的UpdUpdUpd

    正确的O(n)O(n)O(n)判环方式是用inqinqinq数组存每个点是否在当前dfsdfsdfs栈中,如果下一个点已经在栈中那么存在环,returnreturnreturn时出栈。

BZOJ 4013/Luogu P3240 [HNOI2015] 实验比较 (树形DP)的更多相关文章

  1. P3240 [HNOI2015]实验比较 树形DP

    \(\color{#0066ff}{ 题目描述 }\) 小D 被邀请到实验室,做一个跟图片质量评价相关的主观实验.实验用到的图片集一共有 \(N\) 张图片,编号为 \(1\) 到\(N\).实验分若 ...

  2. [BZOJ4013][HNOI2015]实验比较(树形DP)

    4013: [HNOI2015]实验比较 Time Limit: 5 Sec  Memory Limit: 512 MBSubmit: 756  Solved: 394[Submit][Status] ...

  3. luogu P3240 [HNOI2015]实验比较

    传送门 首先根据题目条件,题目中如果是=的点可以缩起来,然后\(a<b\)连边\(a\rightarrow b\),而且所有点入度为最多1,那么判掉有环的不合法情况,题目中的依赖关系就是一颗外向 ...

  4. [HNOI2015]实验比较 树形dp+组合数学

    在合并的时候有可以加等于,或者继续用小于, 比如siz[x]和siz[y]合并,小于的区间为max(siz[x],siz[y])<=k<=siz[x]+siz[y], 然后就是合并成多少个 ...

  5. [BZOJ 1907] 树的路径覆盖 【树形DP】

    题目链接:BZOJ - 1907 题目分析 使用树形 DP,f[x][0] 表示以 x 为根的子树不能与 x 的父亲连接的最小路径数(即 x 是一个折线的拐点). f[x][1] 表示以 x 为根的子 ...

  6. bzoj 4871: [Shoi2017]摧毁“树状图” [树形DP]

    4871: [Shoi2017]摧毁"树状图" 题意:一颗无向树,选两条边不重复的路径,删去选择的点和路径剩下一些cc,求最多cc数. update 5.1 : 刚刚发现bzoj上 ...

  7. BZOJ.4199.[NOI2015]品酒大会(后缀自动机 树形DP)

    BZOJ 洛谷 后缀数组做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 只考虑求极长相同子串,即所有后缀之间的LCP. 而后缀的LCP在后缀树的LCA处.同差异这道题,在每个点处 ...

  8. BZOJ.3611.[HEOI2014]大工程(虚树 树形DP)

    题目链接 要求的和.最大值.最小值好像都可以通过O(n)的树形DP做,总询问点数<=2n. 于是建虚树就可以了.具体DP见DP()函数,维护三个值sum[],mx[],mn[]. sum[]要开 ...

  9. BZOJ 1040 ZJOI 2008 骑士 基环树林+树形DP

    题目大意:有一些骑士.他们每个人都有一个权值.可是因为一些问题,每个骑士都特别讨厌还有一个骑士.所以不能把他们安排在一起.求这些骑士所组成的编队的最大权值和是多少. 思路:首先貌似是有向图的样子,可是 ...

随机推荐

  1. win10系统,jdk环境变量配置,编辑系统变量窗口显示旧版单行和新版列表问题

    大家好,今天说一下我在配置jdk环境变量时遇到的编辑系统变量窗口显示问题. 首先我们说一下如何配置jdk环境变量. 右击此电脑,点击属性. 跳出如下窗口,点击高级系统设置. 跳出如下窗口,点击环境变量 ...

  2. LC 144. / 94. / 145. Binary Tree Preorder/ Inorder/ PostOrder Traversal

    题目描述 144. Binary Tree Preorder Traversal 94. Binary Tree Inorder Traversal 145. Binary Tree Postorde ...

  3. IntelliJ Idea基于Maven创建SpringMVC程序

    1. 创建Maven工程 网上很多资料,不再详细介绍,请参看IntelliJ IDEA 创建 hello world Java web Maven项目从头到尾都有图有真相2017版本 有关settin ...

  4. 字符串模式匹配算法——BM、Horspool、Sunday、KMP、KR、AC算法

    ref : https://dsqiu.iteye.com/blog/1700312 本文内容框架: §1 Boyer-Moore算法 §2 Horspool算法 §3 Sunday算法 §4 KMP ...

  5. poj 2406 求最短重复字串

    题解: KMP中next数组的巧妙运用.在这里我们假设这个字符串的长度是len,那么如果len可以被len-next[len]整除的话,我们就可以说len-next[len]就是那个最短子串的长度为什 ...

  6. SOLID Principles

    Intention: more understandable, easier to maintain and easier to extend.(通过良好的设计使得代码easy and simple, ...

  7. 组装技术的新进展 New advances in sequence assembly.

    组装技术的新进展 1.测序和组装 很难想象今天距离提出测序和组装已经有40年啦.我们回头来看一下这个问题. “With modern fast sequencing techniques and su ...

  8. Ubuntu 14.04 用户如何安装深度音乐播放器和百度音乐插件

    播放本地音乐或者收听国外的音乐电台,Ubuntu 14.04 自带的音乐播放器 Rhythmbox 完全能够满足,但是如果你想有像酷狗那样的国内播放器就需要折腾一下,还好有深度音乐播放器,这是一款完全 ...

  9. .NET中AOP实现

    静态织入,如:PostSharp(收费)动态织入1.使用Castle DynamicProxy不太方便的是需要在AOP的方法上加上virual关键字,配置较繁琐https://blog.csdn.ne ...

  10. centos源码安装nginx

    1.安装依赖 nginx对以下工具包有依赖,我们可以一键安装,命令: yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-dev ...