http://www.lydsy.com/JudgeOnline/problem.php?id=4013 (题目链接)

题意

  给出$n$个数的$m$个大小关系,问它们之间可以形成的单调不降的序列有多少种。

Solution

  首先,因为等于号相连的两个数位置互换不会产生新的方案,我们先用并查集把用等号相连的点全部缩成一个。如果此时的图中出现了环,那么答案为$0$。考虑答案不为$0$的情况怎么处理。此时的图已经成为了一个DAG,我们需要在上面统计方案。容易发现,对于一个点,有分有合,合的情况很好处理,分的情况就很尴尬了,什么?你说每一个点只有一条入边?(哔了狗了)。因为并查集缩点后整个图已经变成了一棵树,我们考虑如何进行树形dp。

  $f[x][i]$表示在$x$的子树中,组成的序列用$<$相连的等价类个数为$i$个的序列方案,其中等价类就表示由等号相连的一坨数。不妨设$y$是$x$的某个儿子,那么转移:

\begin{aligned}  g[i+l]=f[x][i]*f[y][j]*\binom{i-1+l}{j-1}*\binom{j-1}{k-l}   \end{aligned}

  其中$i\in[1,size[x]]$,$j\in[1,size[y]]$,$l\in[max(0,k-j+1),k]$。$g$是一个临时的存储答案的数组。$l$是我们枚举的$y$所贡献的等价类,那么剩下的$k-l$就是$y$中与原本$x$中相等的数的个数。$x$永远排在序列首位而且不会与任意一个数相等。$\binom{i-1+l}{j-1}$表示两个无相对关系的已经排序好的序列合并为一个序列的方案。$\binom{j-1}{k-l}$表示在$x$的$j-1$个数中选出与$y$的$k-l$个数相等的数的方案。

细节

  可能是个森林,所以用一个超级源点连向若干根节点。

代码

// bzoj4013
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define LL long long
#define inf (1ll<<30)
#define MOD 1000000007
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=200;
LL C[maxn][maxn],f[maxn][maxn],g[maxn];
int head[maxn],size[maxn],vis[maxn],fa[maxn],r[maxn],n,m,c,cnt,sum;
struct data {int u,v;}a[maxn];
struct edge {int to,next;}e[maxn]; int find(int x) {
return x==fa[x] ? x : fa[x]=find(fa[x]);
}
void link(int u,int v) {
e[++cnt]=(edge){v,head[u]};head[u]=cnt;
}
bool bfs() {
queue<int> q;q.push(0);
int tot=0;
while (!q.empty()) {
int x=q.front();q.pop();tot++;
for (int i=head[x];i;i=e[i].next)
if (!--r[e[i].to]) q.push(e[i].to);
}
return tot==sum+1;
}
void dfs(int x) {
vis[x]=f[x][1]=size[x]=1;
for (int i=head[x];i;i=e[i].next) if (!vis[e[i].to]) {
int y=e[i].to;dfs(y);
for (int j=1;j<=size[x];j++) {
if (!f[x][j]) continue;
for (int k=1;k<=size[y];k++) {
if (!f[y][k]) continue;
for (int l=max(0,k-j+1);l<=k;l++)
(g[j+l]+=f[x][j]*f[y][k]%MOD*C[j+l-1][j-1]%MOD*C[j-1][k-l]%MOD)%=MOD;
}
}
size[x]+=size[e[i].to];
for (int i=1;i<=size[x];i++) f[x][i]=g[i],g[i]=0;
}
}
int main() {
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) fa[i]=i;
for (int i=0;i<=n;i++) C[i][0]=1;
for (int i=1;i<=n;i++)
for (int j=1;j<=i;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%MOD;
for (int u,v,i=1;i<=m;i++) {
char ch[2];scanf("%d%s%d",&u,ch,&v);
if (ch[0]=='=') if (find(u)!=find(v)) fa[find(u)]=find(v);
if (ch[0]=='<') a[++c]=(data){u,v};
}
for (int i=1;i<=c;i++) {
int u=find(a[i].u),v=find(a[i].v);
link(u,v);r[v]++;
}
for (int i=1;i<=n;i++) if (fa[i]==i) {
sum++;
if (!r[i]) link(0,i),r[i]++;
}
if (!bfs()) {puts("0");return 0;}
dfs(0);
int ans=0;
for (int i=1;i<=n+1;i++) (ans+=f[0][i])%=MOD;
printf("%d",ans);
return 0;
}

【bzoj4013】 HNOI2015—实验比较的更多相关文章

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

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

  2. BZOJ4013 : [HNOI2015]实验比较

    首先用并查集将等号缩点,然后拓扑排序判断有没有环,有环则无解,否则通过增加超级源点$0$,可以得到一棵树. 设$f[x][y]$表示$x$子树里有$y$种不同的数字的方案数,由底向上DP. 对于当前点 ...

  3. 【BZOJ4013】[HNOI2015]实验比较(动态规划)

    [BZOJ4013][HNOI2015]实验比较(动态规划) 题面 BZOJ 洛谷 题解 看题目意思就是给你一棵树,连边表示强制顺序关系.然后你要给点染色,在满足顺序关系的情况下,将序列染成若干个颜色 ...

  4. 4013: [HNOI2015]实验比较

    4013: [HNOI2015]实验比较 链接 分析: 首先把等号用并查集合并起来. 由于只存在最多一个质量不比i差的数,发现这是森林.若x<y,连边x->y.于是建虚拟根节点0. 然后树 ...

  5. bzoj 4013: [HNOI2015]实验比较

    Description 小D 被邀请到实验室,做一个跟图片质量评价相关的主观实验.实验用到的图片集一共有 N 张图片,编号为 1 到 N.实验分若干轮进行,在每轮实验中,小 D会被要求观看某两张随机选 ...

  6. [HNOI2015]实验比较

    Description 小D 被邀请到实验室,做一个跟图片质量评价相关的主观实验.实验用到的图片集一共有 N 张图片,编号为 1 到 N.实验分若干轮进行,在每轮实验中,小 D会被要求观看某两张随机选 ...

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

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

  8. luogu P3240 [HNOI2015]实验比较

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

  9. 【BZOJ】4013: [HNOI2015]实验比较

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4013 中第i 条涉及的图片对为(KXi, Xi),判断要么是KXi < Xi ,要么 ...

随机推荐

  1. java基础---JDK、JRE、JVM的区别和联系

    当我们学习java语言时,首先需要安装到我们电脑上的就是jdk.jdk是java语言的开发环境,只有安装了jdk,我们才能使用java语言开发程序. JDK=JRE+开发工具包 JRE=JVM+核心类 ...

  2. 006 --MySQL索引原理

    一 .索引的概念? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句的优化 ...

  3. 使用AD对Linux客户端进行身份验证

    https://technet.microsoft.com/zh-cn/library/2008.12.linux.aspx

  4. 基于Java Junit测试框架 + jmeter 做压力测试

    1.JUnit 用户指南请查阅: https://junit.org/junit5/docs/current/user-guide/ 以一下代码为例:add接口 代码测试正常后,导出包: 下一步: j ...

  5. BOM 头是什么,怎么除去

    WINDOWS自带的记事本,在保存一个以 UTF-8 编码的文件时,会在文件开始的地方插入三个不可见的字符(0xEF 0xBB 0xBF,即BOM).它是一串隐藏的字符,用于让记事本等编辑器识别这个文 ...

  6. SQL IF while 游标

    -- if语句使用示例 declare @a int set @a=1 begin print @a =@a+1 end else begin print 'noooo' end -- while语句 ...

  7. mysql实现oracle sequence方案

    转自: http://blog.csdn.net/javaGirlOne/article/details/47256183 背景:先总结一下MYSQL 自增长与ORACLE 序列的区别: 自增长只能用 ...

  8. Homebrew -- 安装与使用

    使用 React Native,必须安装的依赖有:Node.Watchman 和 React Native 命令行工具以及 Xcode. 推荐使用Homebrew来安装 Node 和 Watchman ...

  9. final发布--PSP Daily软件功能书(最终版)

    一.开发背景 你在完成了一周的软件工程作业后,需要提交一个PSP图表,里面有4项,如下所示: 1.本周PSP表格,包含每项任务的开始.中断.结束.最终时间,格式如下: 2.本周进度条,包含从开始到现在 ...

  10. golang string转json的一些坑

    先带来点冷知识,不知道大家知不知道,反正我刚知道... 大佬们都知道怎么在string中给string类型赋值带双引号的字符串,没错就是用反斜杠,如下: msg := "{\"na ...