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位同学排成合唱队 ...
随机推荐
- SQLServer2008 关于CASE WHEN
CASE WHEN的两种格式 1.简单Case函数 CASE sex WHEN '1' THEN '男' WHEN '2' THEN '女' ELSE '其他' END 2.Case搜索函数 CASE ...
- ThinkPHP3.2.3对数据的添、删、改、查(CURD)
对数据的添加: public function form() { parent::common(); $obj = D('Leave'); if (IS_POST) { $data = I('post ...
- jQuery学习笔记之jQuery的Ajax(3)
jQuery学习笔记之jQuery的Ajax(3) 6.jQuery的Ajax插件 源码地址: https://github.com/iyun/jQueryDemo.git ------------- ...
- Android 微博sdk接入授权指南
1:首先在微博官方注册账号,官方地址是:http://open.weibo.com/然后创建一个新应用. 2:当然我们得现在自己电脑上创建一个应用,例如包名叫com.winorout.weib ...
- js 事件冒泡、事件捕获、stopPropagation、preventDefault
转自:http://www.jb51.net/article/42492.htm (1)冒泡型事件:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发. IE 5.5: ...
- System.Web.Caching.Cache类 Asp.Net缓存 各种缓存依赖
Cache类,是一个用于缓存常用信息的类.HttpRuntime.Cache以及HttpContext.Current.Cache都是该类的实例. 一.属性 属性 说明 Count 获取存储在缓存中的 ...
- Dynamics CRM查询实体共享给哪些人
在mscrm中,如果想查询一条记录共享给了哪些人,需要用到PrincipalObjectAccess 表,sql如下: select u.FullName,a.RC_name,sup.SystemUs ...
- raspberry pi树莓派设置
买了个pi3b 安装系统 需要class10 TF卡.读卡器 下载系统并解压Raspbianhttps://www.raspberrypi.org/downloads/raspbian/访问慢的话请用 ...
- beetl模板入门例子
加入maven依赖 <dependency> <groupId>org.beetl</groupId> <artifactId>beetl-core&l ...
- Vue: axios 请求封装及设置默认域名前缀 (for Vue 2.0)
1. 实现效果 以get方法向http://192.168.32.12:8080/users 发起请求.获取数据并进行处理 this.apiGet('/users', {}) .then((res) ...