偏序集上的最小链覆盖等价于求最长反链

最小不交链覆盖等于传递闭包后最小链覆盖

最小链覆盖大小等于点数减去二分图最大匹配大小

二分图最小点覆盖大小等于二分图匹配大小

二分图最小点覆盖与二分图最大独立集对偶

建图完后,这个二分图最大独立集等价于最长反链。

于是两道题

1143: [CTSC2008]祭祀river

求偏序集上的最长反链

转换成偏序集上的最小链覆盖

求个闭包,转换成最小路径覆盖,二分图匹配一发

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue> const int MAXN = 210;
const int MAXM = MAXN * MAXN * 2;
const int INF = 0x3f3f3f3f;
int head[MAXN], nxt[MAXM], to[MAXM], val[MAXM], tot = 1;
inline void addedge(int b, int e, int v) {
nxt[++tot] = head[b]; to[head[b] = tot] = e; val[tot] = v;
nxt[++tot] = head[e]; to[head[e] = tot] = b; val[tot] = 0;
}
std::queue<int> q;
int S, T, dis[MAXN];
bool bfs() {
for (int i = S; i <= T; ++i) dis[i] = 0;
dis[S] = 1; q.push(S);
while (!q.empty()) {
int t = q.front(); q.pop();
for (int i = head[t]; i; i = nxt[i])
if (val[i] && !dis[to[i]]) {
dis[to[i]] = dis[t] + 1;
q.push(to[i]);
}
}
return dis[T] > 0;
}
int dinic(int u, int minv) {
if (u == T || !minv) return minv;
int t, res = 0;
for (int i = head[u]; i; i = nxt[i])
if (val[i] && dis[to[i]] == dis[u] + 1 && (t = dinic(to[i], std::min(minv, val[i])))) {
val[i] -= t;
val[i ^ 1] += t;
res += t;
minv -= t;
if (!minv) break;
}
if (!res) dis[u] = -1;
return res;
} int n, m, t1, t2, f[MAXN][MAXN];
int main() {
scanf("%d%d", &n, &m);
S = 0, T = n << 1 | 1;
for (int i = 1; i <= m; ++i) {
scanf("%d%d", &t1, &t2);
f[t1][t2] = true;
}
for (int k = 1; k <= n; ++k)
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
f[i][j] |= f[i][k] & f[k][j];
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
if (f[i][j])
addedge(i, j + n, 1);
for (int i = 1; i <= n; ++i) {
addedge(S, i, 1);
addedge(i + n, T, 1);
}
int ans = n;
while (bfs()) ans -= dinic(S, INF);
printf("%d\n", ans);
return 0;
}

3997: [TJOI2015]组合数学

 给出一个网格图,其中某些格子有财宝,每次从左上角出发,只能向下或右走。问至少走多少次才能将财宝捡完。此对此问题变形,假设每个格子中有好多财宝,而每一次经过一个格子至多只能捡走一块财宝,至少走多少次才能把财宝全部捡完。

求偏序集上的最小链覆盖,转换为最长反链覆盖

于是只要DP出反链就好了,前(其实是后)缀和优化一下

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> const int MAXN = 1010;
int f[MAXN][MAXN], suc[MAXN][MAXN], map[MAXN][MAXN], n, m;
inline void getmax(int & x, const int y) { if (x < y) x = y; } int main() {
int T; scanf("%d", &T);
while (T --> 0) {
scanf("%d%d", &n, &m);
for (int i = 0; i <= n + 1; ++i)
for (int j = 0; j <= m + 1; ++j)
f[i][j] = suc[i][j] = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) scanf("%d", map[i] + j);
for (int j = m; j; --j) {
getmax(f[i][j], suc[i - 1][j + 1] + map[i][j]);
suc[i][j] = std::max(suc[i][j + 1], suc[i - 1][j]);
getmax(suc[i][j], f[i][j]);
}
}
printf("%d\n", suc[n][1]);
}
return 0;
}

1143, 3997: Dilworth定理的简单应用的更多相关文章

  1. bzoj 3997 Dilworth定理

    看到这道题感觉像是网络流,如果没有权值,可以用DAG最小路径覆盖,有权值,感觉可以求一个上下界最小可行流,但内存卡了....时间估计也悬. 正解要用到一些数学知识,这里梳理一下: 定义: 偏序关系: ...

  2. BZOJ.1143.[CTSC2008]祭祀(Dilworth定理 最大流ISAP)

    题目链接 题目是求最长反链,反链指点集内任意两点不能互相到达. 根据Dilworth定理,在DAG中,\[最长反链 = 最小路径覆盖 = V - 最大匹配数\] 用Floyd求一遍传递闭包后,在所有可 ...

  3. 【codevs1044】导弹拦截问题与Dilworth定理

    题目描述 Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某 ...

  4. (转载)偏序集的Dilworth定理学习

    导弹拦截是一个经典问题:求一个序列的最长不上升子序列,以及求能最少划分成几组不上升子序列.第一问是经典动态规划,第二问直接的方法是最小路径覆盖, 但是二分图匹配的复杂度较高,我们可以将其转化成求最长上 ...

  5. codevs1044:dilworth定理

    http://www.cnblogs.com/submarine/archive/2011/08/03/2126423.html dilworth定理的介绍 题目大意:求一个序列的lds 同时找出这个 ...

  6. 如何使用Dilworth定理

    相关例题:NOIP 1999导弹拦截 遇到这题不会去网上搜Dilworth定理,太难受了,看不懂证明 但是,我知道怎么使用了,管那么多,会用就完事了 学习自这篇文章 -1.为什么我不想学证明这个定理 ...

  7. 洛谷P1020 导弹拦截 题解 LIS扩展题 Dilworth定理

    题目链接:https://www.luogu.com.cn/problem/P1020 题目大意: 给你一串数,求: 这串数的最长不上升子序列的长度: 最少划分成多少个子序列是的这些子序列都是不上升子 ...

  8. 偏序集的Dilworth定理

    定理1 令(X,≤)是一个有限偏序集,并令r是其最大链的大小.则X可以被划分成r个但不能再少的反链.其对偶定理称为Dilworth定理:定理2 令(X,≤)是一个有限偏序集,并令m是反链的最大的大小. ...

  9. hdu1051(LIS | Dilworth定理)

    这题根据的Dilworth定理,链的最小个数=反链的最大长度 , 然后就是排序LIS了 链-反链-Dilworth定理 hdu1051 #include <iostream> #inclu ...

随机推荐

  1. AtCoder Beginner Contest 131 Task F. Must Be Rectangular

    Score: 600 points Approach 固定横坐标 $x$,考虑横坐标为 $x$ 的竖直线上最多可以有几个点. Observations 若最初两条竖直线 $x_1$.$x_2$ 上都有 ...

  2. jinja2介绍

    jinja2介绍 jinja2是Flask作者开发的一个模板系统,起初是仿django模板的一个模板引擎,为Flask提供模板支持,由于其灵活,快速和安全等优点被广泛使用. jinja2的优点 jin ...

  3. Win32汇编-创建窗体代码

    1.一个最简单的窗体的创建 ;>>>>>>>>>>>>>>>>>>>>>& ...

  4. Java集合框架中的元素

    之前有一篇笔记,讲的是集合和泛型,这几天看Java集合中几个接口的文档,思绪非常混乱,直到看到Oracle的“The Collections Framwork”的页面,条理才清晰些,现在进行整理. 一 ...

  5. oracle 安装后参数调整

    关闭11g 新特性 开归档 oracle 11g安装完成需修改:1.关闭审计alter system set audit_trail=none scope=spfile sid='*'; 防止ORA- ...

  6. Mybatis实际练习

    1.mybatis在xml文件中处理大于号小于号的方法 第一种方法: 用了转义字符把>和<替换掉,然后就没有问题了. SELECT * FROM test WHERE 1 = 1 AND ...

  7. vi 必须要学会的技能

    vi与vim vi编辑器是所有Unix及Linux系统下标准的编辑器,他就相当于windows系统中的记事本一样,它的强大不逊色于任何最新的文本编辑器.他是我们使用Linux系统不能缺少的工具.由于对 ...

  8. 测试数年来,我只提了几十个bug

    ---恢复内容开始--- 测试做了十来年,大大小小的项目产品已经记不清了,开发们在一如既往地改着改了无数遍的bug,测试也一如既往的提着提了无数遍的bug,那么今天笔者对以往的bug类型做一个简单的总 ...

  9. PAT Basic 1014 福尔摩斯的约会 (20 分)

    大侦探福尔摩斯接到一张奇怪的字条:我们约会吧! 3485djDkxh4hhGE 2984akDfkkkkggEdsb s&hgsfdk d&Hyscvnm.大侦探很快就明白了,字条上奇 ...

  10. 【AGC006 C】Rabbit Exercise

    题意 有 \(n\) 只兔子在数轴上,第 \(i\) 只兔子的初始坐标为整数 \(x_i\). 现在这些兔子会按照下面的规则做体操.每一轮体操都由 \(m\) 次跳跃组成:在第 \(j\) 次跳跃时, ...