luogu2766 最长不下降子序列问题 DP 网络流
题目大意:给定正整数序列x1,...,xn 。(1)计算其最长不下降子序列的长度s。(不一定是否连续)(2)计算从给定的序列中最多可取出多少个长度为s的不下降子序列。(序列内每一个元素不可重复)(3)如果允许在取出的序列中多次使用x1和xn,则从给定序列中最多可取出多少个长度为s的不下降子序列。
关键词:不相交路径,拆点
(1)DP经典题LIS。令原序列为A[i],DP[i]表示以i为结尾的不下降子序列长度最长为多少。
(2)
不相交路径:想象有一个流把一个子序列内的每一个元素都串了起来。后一个元素与前一个元素可连接的标志是DP[j]=DP[i]+1且A[i]<=A[j]。
拆点:每个元素只能访问一次,因此把一个元素拆成一条容量为1的边,两元素若可连接,则将前元素的to点连后元素的from点。为了从头开始,从尾结束,因此将S与DP[i]=1的元素边的from点连,DP[i]=S的元素边的to点与T连。然后求最大流即可。
(3)将与1元素边的from点和与n元素边的to节点相连的正向边容量设为∞,然后求最大流。
#include <cstdio>
#include <cstring>
#include <cassert>
#include <queue>
#include <algorithm>
#include <cmath>
using namespace std; #define LOOP(i,n) for(int i=1; i<=n; i++)
const int MAX_NODE = , MAX_EDGE = MAX_NODE*MAX_NODE, INF = 0x3f3f3f3f;//注意MAX_NODE=500*2
int A[MAX_NODE], DP[MAX_NODE];
int Tot, MaxLen, Sid, Tid;
//#define test struct Dinic
{
struct Edge;
struct Node; struct Node
{
int Id, Level;
Edge* Head;
Edge *DfsFrom;
}; struct Edge
{
int Cap, OrgCap;
Node *From, *To;
Edge *Next, *Rev;
Edge(int cap, Node *from, Node *to, Edge *next) :Cap(cap), OrgCap(cap), From(from), To(to), Next(next) {}
}; Node _nodes[MAX_NODE];
Edge *_edges[MAX_EDGE];
int _vCount, _eCount;
Node *Start, *Target; void Init(int Sid, int Tid, int vCount)
{
memset(_nodes, , sizeof(_nodes));
memset(_edges, , sizeof(_edges));
_eCount = ;
Start = Sid + _nodes;
Target = Tid + _nodes;
_vCount = vCount;
} void Recover()
{
LOOP(i, _eCount)
_edges[i]->Cap = _edges[i]->OrgCap;
} Edge* AddEdge(Node *from, Node *to, int cap)
{
Edge *e = _edges[++_eCount] = new Edge(cap, from, to, from->Head);
e->From->Head = e;
return e;
} void Build(int uId, int vId, int eCap)
{
Node *u = uId + _nodes, *v = vId + _nodes;
u->Id = uId;
v->Id = vId;
Edge *edge1 = AddEdge(u, v, eCap), *edge2 = AddEdge(v, u, );
edge1->Rev = edge2;
edge2->Rev = edge1;
} bool Bfs()
{
for (int i = ; i <= _vCount; i++)
_nodes[i].Level = ;
static queue<Node*> q;
Start->Level = ;
q.push(Start);
while (!q.empty())
{
Node *u = q.front();
q.pop();
for (Edge *e = u->Head; e; e = e->Next)
{
assert(e->Cap >= );
if (!e->To->Level && e->Cap)
{
e->To->Level = u->Level + ;
q.push(e->To);
}
}
}
return Target->Level;
} int Dfs(Node *cur, int limit)
{
if (cur == Target)
return limit;
if (limit == )
return ;
int curTake = ;
for (Edge *e = cur->DfsFrom; e; cur->DfsFrom = e = e->Next)
{
if (e->To->Level == cur->Level + && e->Cap)
{
int nextTake = Dfs(e->To, min(limit - curTake, e->Cap));
e->Cap -= nextTake;
e->Rev->Cap += nextTake;
curTake += nextTake;
}
if (limit - curTake == )
break;
}
return curTake;
} int Proceed()
{
int ans = ;
while (Bfs())
{
for (int i = ; i <= _vCount; i++)
_nodes[i].DfsFrom = _nodes[i].Head;
ans += Dfs(Start, INF);
}
return ans;
}
}g; void P1()
{
LOOP(j, Tot)
{
int maxLen = ;
LOOP(i, j - )
if (A[i] <= A[j])
maxLen = max(maxLen, DP[i]);
DP[j] = maxLen + ;
}
MaxLen = ;
LOOP(i, Tot)
MaxLen = max(MaxLen, DP[i]);
printf("%d\n", MaxLen);
} void P2()
{
Sid = Tot * + , Tid = Tot * + ;
g.Init(Sid, Tid, Tid);
LOOP(i, Tot)
g.Build(i, i + Tot, );
LOOP(i, Tot)
{
if (DP[i] == )
g.Build(Sid, i, );
if (DP[i] == MaxLen)
g.Build(i + Tot, Tid, );
else
for (int j = i + ; j <= Tot; j++)
if (DP[j] == DP[i] + && A[j] >= A[i])
g.Build(i + Tot, j, );
}
printf("%d\n", g.Proceed());
} void P3()
{
for (Dinic::Edge* e = g._nodes[].Head; e; e = e->Next)
{
if (e->To->Id == + Tot)
e->OrgCap = INF;
else if (e->To == g.Start)
e->Rev->OrgCap = INF;
}
for (Dinic::Edge *e = g._nodes[Tot * ].Head; e; e = e->Next)
{
if (e->To->Id == Tot)
e->Rev->OrgCap = INF;
else if (e->To == g.Target)
e->OrgCap = INF;
}
g.Recover();
printf("%d\n", g.Proceed());
} int main()
{
#ifdef _DEBUG
freopen("c:\\noi\\source\\input.txt", "r", stdin);
#endif
scanf("%d", &Tot);
LOOP(i, Tot)
scanf("%d", i + A);
P1();
P2();
P3();
return ;
}
注意:
1.本题是“不下降”,而不是“上升”。因此(1)题DP时应该为A[i]<=A[j],而不是A[i]<A[j]。
2.(2)问不要忘了判断元素可连接的标志还有A[i]<=A[j]。
3.(3)题改容量时注意改的到底时正向边的容量还是反向边的容量,要清楚。
luogu2766 最长不下降子序列问题 DP 网络流的更多相关文章
- 最长不下降子序列//序列dp
最长不下降子序列 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 求最长不下降子序列的长度 输入格式 第一行为n,表示n个数第二行n个数 输出格式 最长不下降 ...
- luogu2766 最长不下降子序列问题
第一问DP水过.dp[i]代表以i结尾的最长不下降子序列长度. 二三问网络流. 第二问是说每个子序列不能重复使用某个数字. 把每个点拆成p(i),q(i).连边. 要是dp[i]=1,连源,p(i) ...
- Codeforces Round #323 (Div. 2) Once Again... CodeForces - 582B 最长非下降子序列【dp】(不明白)
B. Once Again... time limit per test 1 second memory limit per test 256 megabytes input standard inp ...
- HDU 1087 最长不下降子序列 LIS DP
Nowadays, a kind of chess game called “Super Jumping! Jumping! Jumping!” is very popular in HDU. May ...
- SPOJ 4053 - Card Sorting 最长不下降子序列
我们的男主现在手中有n*c张牌,其中有c(<=4)种颜色,每种颜色有n(<=100)张,现在他要排序,首先把相同的颜色的牌放在一起,颜色相同的按照序号从小到大排序.现在他想要让牌的移动次数 ...
- 【DP】最长不下降子序列问题(二分)
Description 给你一个长度为n的整数序列,按从左往右的顺序选择尽量多的数字并且满足这些数字不下降. Thinking 朴素dp算法:F[i]表示到第i位为止的最长不下降子序列长度 F[i]= ...
- 洛谷 P2766 最长不下降子序列问【dp+最大流】
死于开小数组的WA?! 第一问n方dp瞎搞一下就成,f[i]记录以i结尾的最长不下降子序列.记答案为mx 第二问网络流,拆点限制流量,s向所有f[i]为1的点建(s,i,1),所有f[i]为mx(i+ ...
- 「10.19」最长不下降子序列(DP)·完全背包问题(spfa优化DP)·最近公共祖先(线段树+DFS序)
我又被虐了... A. 最长不下降子序列 考场打的错解,成功调了两个半小时还是没A, 事实上和正解的思路很近了,只是没有想到直接将前$D$个及后$D$个直接提出来 确实当时思路有些紊乱,打的时候只是将 ...
- NOIP 2004 T3 合唱队形(DP、最长上升/下降子序列)
链接:https://ac.nowcoder.com/acm/contest/1082/C来源:牛客网 题目描述 N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队 ...
随机推荐
- Spring Boot (11) mybatis 关联映射
一对多 查询category中的某一条数据,同时查询该分类下的所有Product. Category.java public class Category { private Integer id; ...
- USB 接口探测分类
USB 接口探测分类 SDP (Standand Downstream Port) 标准下行接口 标准USB都支持的接口 这种端口的D+和D-线上具有15kΩ下拉电阻.限流值如上讨论:挂起时为2.5m ...
- php登陆和注册
注册界面 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF- ...
- 【PLSQL】游标
Oracle中的SQL在执行时需要分配一块内存区域,这块内存区域叫做上下文区. 上下文区中记录了SQL语句的处理信息,这些信息包括:查询返回的数据行.查询所处理的数据的行号.指向共享池中的已分析的SQ ...
- 【SQL】CONNECT BY 层次化查询
层次化查询,顾名思义就是把查询结果有层次的呈现出来.层次化查询结果类似于树状结构,最顶端的是“根节点”,下面是“父节点”,没有子节点的是“叶节点”. 为了让一个或多个表具有层次关系,必须使用相关的字段 ...
- 三维重建:SLAM的尺度和方法论问题
百度百科的定义.此文引用了其他博客的一些图像,如有侵权,邮件联系删除. 作为算法的SLAM,被称为同步相机位姿确定和地图构建.作为一个工程的SLAM,有众多的算法. 在计算机视觉中, 三维重建是指根据 ...
- Tomcat 服务器中jsp页面乱码
<Connector port="80" protocol="HTTP/1.1" connectionTimeout=&quo ...
- spring学习地址
http://developer.51cto.com/art/201006/205212_2.htm
- S-HR快速查看shr日志
http://localhost:6888/shr/appData.do?method=getApplicationLog&logFile=apusic.log.0&instance= ...
- 【剑指Offer】10、矩形覆盖
题目描述: 我们可以用2 X 1的小矩形横着或者竖着去覆盖更大的矩形.请问用n个2 X 1的小矩形无重叠地覆盖一个2 X n的大矩形,总共有多少种方法? 解题思路: 我们可以以2 X ...