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. 2.3 Oracle之DDL 语句(约束、伪列、视图、序列、同义词) 精简版

    DDL Data Definition(重点) (n. 定义:[物] 清晰度:解说)用于定义数据的结构,创建,修改,删除数据库对象 一.表的增删改查 1.创建表:CREATE TABLE temp A ...

  2. 三种UIScrollView嵌套实现方案

    背景 随着产品功能不断的迭代,总会有需求希望在保证不影响其他区域功能的前提下,在某一区域实现根据选择器切换不同的内容显示. 苹果并不推荐嵌套滚动视图,如果直接添加的话,就会出现下图这种情况,手势的冲突 ...

  3. jQuery的基本使用

    一.jQuery简介 jQuery是一个快速.简洁的JavaScript框架,它封装了JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作.事件处理.动 ...

  4. dmesg命令详解

    基础命令学习目录 http://linux.cn/article-3587-1.html dmesg 命令的使用范例 下面我们展示一些最负盛名的‘dmesg’命令工具以及其实际使用举例.‘dmesg’ ...

  5. AbstractQueuedSynchronizer 原理分析 - 独占/共享模式(转)

    1.简介 AbstractQueuedSynchronizer (抽象队列同步器,以下简称 AQS)出现在 JDK 1.5 中,由大师 Doug Lea 所创作.AQS 是很多同步器的基础框架,比如 ...

  6. 使用谷歌浏览器调试WEB前端的一些必备调试技巧

    转载:http://www.techug.com/post/chrome-debug-tips.html Chrome的开发者工具是个很强大的东西,相信程序员们都不会陌生,不过有些小功能可能并不为大众 ...

  7. 第二次作业(homework-02)成绩公布

    学位后三位和对应成绩: 057 0008 4011 4012 7014 5015 5017 6018 0019 0026 2027 7036 0038 7.5046 7048 6.5051 0061 ...

  8. OO的第一次死亡

    久仰OO大名,总是想着提前做点准备,其实到头来还是什么准备都没有做,所以这学期就是从零开始的面向对象生活,也因此遇到了很多的问题. 第一次作业——多项式加减 第一次作业历来是较为简单的,但是对于面向对 ...

  9. C#编程之神奇程序找数

    C#编程之神奇程序找数 问题1:这个程序要找的是符合什么条件的数? 问题2:这样的数存在么?符合这一条件的最小的数是什么? 问题3:在电脑上运行这一程序,你估计多长时间才能输出第一个结果?时间精确到分 ...

  10. Java网络编程二:Socket详解

    Socket又称套接字,是连接运行在网络上两个程序间的双向通讯的端点. 一.使用Socket进行网络通信的过程 服务端:服务器程序将一个套接字绑定到一个特定的端口,并通过此套接字等待和监听客户端的连接 ...