Luogu 2766 - 最长不下降子序列问题 - [LIS问题][DP+网络流]
题目链接:https://www.luogu.org/problemnew/show/P2766
题解(大量参考https://blog.csdn.net/ZscDst/article/details/82423342):
第一问,可以用DP求解,用 $f[i]$ 表示以 $a[i]$ 为结尾的最长不减子序列的长度,DP时间复杂度 $O(n^2)$,假设求得长度为 $len$。
第二问我们可以用网络流来求解:
1、由于每个点只能被选一次,所以拆点,控制每个数只能选一次。
2、源点往所有 $f[i]=1$ 的点连一条边权为 $1$ 的边,所有 $f[i]=len$ 的点往汇点连一条边权为 $1$ 的边。
3、如果 j 点是由 i 点转移得到的(即f[i]+1==f[j] && a[i] <= a[j]),那么 i+n 往 j 连一条边权为1的边。
第三问:
$x[1]$ 和 $x[n]$ 可以使用多次,首先 $x[1],x[n]$ 拆出来的两个点之间的容量需要修改。
同时,此题中必然有一条边从源点连向 $x[1]$,所以这条边的容量也要修改。$x[n]$ 不一定是汇点,若 $x[n]$ 是汇点,那么 $x[n]$ 到汇点的边的容量也要修改。
如果重新构图去跑可能会超时,我们知道网络流是可以继续在残量网络中跑的,所以我们直接再添加新边,再继续跑网络流,累加到第二问的答案上,即为第三问的答案。
AC代码:
#include<bits/stdc++.h>
#define I(x) x
#define O(x) (n+x)
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=; int n,x[maxn];
int f[maxn]; struct Edge{
int u,v,c,f;
};
struct Dinic
{
static const int SIZE=*maxn;
int s,t; //源点汇点
vector<Edge> E;
vector<int> G[SIZE];
void init(int l,int r)
{
E.clear();
for(int i=l;i<=r;i++) G[i].clear();
}
void addedge(int from,int to,int cap)
{
E.push_back((Edge){from,to,cap,});
E.push_back((Edge){to,from,,});
G[from].push_back(E.size()-);
G[to].push_back(E.size()-);
}
int dist[SIZE],vis[SIZE];
queue<int> q;
bool bfs() //在残量网络上构造分层图
{
memset(vis,,sizeof(vis));
while(!q.empty()) q.pop();
q.push(s);
dist[s]=;
vis[s]=;
while(!q.empty())
{
int now=q.front(); q.pop();
for(int i=;i<G[now].size();i++)
{
Edge& e=E[G[now][i]]; int nxt=e.v;
if(!vis[nxt] && e.c>e.f)
{
dist[nxt]=dist[now]+;
q.push(nxt);
vis[nxt]=;
}
}
}
return vis[t];
}
int dfs(int now,int flow)
{
if(now==t || flow==) return flow;
int rest=flow,k;
for(int i=;rest> && i<G[now].size();i++)
{
Edge &e=E[G[now][i]]; int nxt=e.v;
if(e.c>e.f && dist[nxt]==dist[now]+)
{
k=dfs(nxt,min(rest,e.c-e.f));
if(!k) dist[nxt]=; //剪枝,去掉增广完毕的点
e.f+=k; E[G[now][i]^].f-=k;
rest-=k;
}
}
return flow-rest;
}
int mf; //存储最大流
int maxflow()
{
mf=;
int flow=;
while(bfs()) while(flow=dfs(s,INF)) mf+=flow;
return mf;
}
}dinic; int main()
{
cin>>n;
for(int i=;i<=n;i++) scanf("%d",&x[i]); int len=;
dinic.init(dinic.s=,dinic.t=*n+);
for(int i=;i<=n;i++)
{
dinic.addedge(I(i),O(i),); f[i]=;
for(int j=;j<i;j++)
if(x[j]<=x[i]) f[i]=max(f[i],f[j]+);
len=max(len,f[i]); if(f[i]==) dinic.addedge(dinic.s,I(i),);
else
{
for(int j=;j<i;j++)
if(x[j]<=x[i] && f[j]+==f[i]) dinic.addedge(O(j),I(i),);
}
}
cout<<len<<endl; for(int i=;i<=n;i++)
if(f[i]==len) dinic.addedge(O(i),dinic.t,); int ans=dinic.maxflow();
cout<<ans<<endl; dinic.addedge(dinic.s,I(),INF), dinic.addedge(I(),O(),INF);
dinic.addedge(I(n),O(n),INF);
if(f[n]==len) dinic.addedge(O(n),dinic.t,INF); cout<<ans+dinic.maxflow()<<endl;
}
Luogu 2766 - 最长不下降子序列问题 - [LIS问题][DP+网络流]的更多相关文章
- 【题解】Luogu P2766 最长不下降子序列问题
原题传送门 实际还是比较套路的建图 先暴力dp一下反正数据很小 第一小问的答案即珂以求出数列的最长不下降子序列的长度s 考虑第二问如何做: 将每个点拆点 从前向后连一条流量为1的边 如果以它为终点的最 ...
- 最长不下降子序列(LIS)
最长上升子序列.最长不下降子序列,解法差不多,就一点等于不等于的差别,我这里说最长不下降子序列的. 有两种解法. 一种是DP,很容易想到,就这样: REP(i,n) { f[i]=; FOR(j,,i ...
- 动态规划——最长不下降子序列(LIS)
最长不降子序列是这样一个问题: 下面介绍动态规划的做法. 令 dp[i] 表示以 A[i] 结尾的最长不下降序列长度.这样对 A[i] 来说就会有两种可能: 如果存在 A[i] 之前的元素 A[j] ...
- 最长不下降子序列(线段树优化dp)
最长不下降子序列 题目大意: 给定一个长度为 N 的整数序列:A\(_{1}\),A\(_{2}\),⋅⋅⋅,A\(_{N}\). 现在你有一次机会,将其中连续的 K 个数修改成任意一个相同值. 请你 ...
- luogu P2766 最长不下降子序列问题
第一问可以直接DP来做,联想上一题,线性规划都可以化为网络流?我们可以借助第一问的DP数组,来建立第二问第三问的网络流图,考虑每一种可能,都是dp数组中满足num[i]>=num[j]& ...
- [Swust OJ 585]--倒金字塔(LIS最长不下降子序列)
题目链接:http://acm.swust.edu.cn/problem/585/ Time limit(ms): 3000 Memory limit(kb): 65535 SWUST国的一支科学 ...
- luogu2766 最长不下降子序列问题
第一问DP水过.dp[i]代表以i结尾的最长不下降子序列长度. 二三问网络流. 第二问是说每个子序列不能重复使用某个数字. 把每个点拆成p(i),q(i).连边. 要是dp[i]=1,连源,p(i) ...
- Libre 6005 「网络流 24 题」最长递增子序列 / Luogu 2766 最长递增子序列问题(网络流,最大流)
Libre 6005 「网络流 24 题」最长递增子序列 / Luogu 2766 最长递增子序列问题(网络流,最大流) Description 问题描述: 给定正整数序列x1,...,xn . (1 ...
- Luogu 1020 导弹拦截(动态规划,最长不下降子序列,二分,STL运用,贪心,单调队列)
Luogu 1020 导弹拦截(动态规划,最长不下降子序列,二分,STL运用,贪心,单调队列) Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺 ...
随机推荐
- CF1119A Ilya and a Colorful Walk
题目地址:CF1119A Ilya and a Colorful Walk \(O(n^2)\) 肯定过不掉 记 \(p_i\) 为从下标 \(1\) 开始连续出现 \(i\) 的个数 那么对于每一个 ...
- POJ 3304 Segments(直线)
题目: Description Given n segments in the two dimensional space, write a program, which determines if ...
- FTP:mget匹配文件名后下载
需求:从FTP某目录取每日构建的apk下载到本地 难点:文件名中有构建时间,而这个时间不算固定值,因此文件名不固定 解决方案:mget匹配文件名后下载 BAT版本: :: Filename:Proje ...
- django日志,django-crontab,django邮件模块
django 日志 四大块,格式器,过滤器,处理器,日志管理器 LOGGING = { 'version': 1, 'disable_existing_loggers': True, 'formatt ...
- java设计模式自我总结---适配器模式
上一篇博客说完了 java 23 中设计模式中的五种 创建性模式,由于篇幅过长,新开一贴今天开始学习结构型模式, 结构型模式包括以下七种:适配器模式.装饰模式.代理模式.外观模式.桥接模式.组合模式. ...
- jfinal undertow web.xml
由于 undertow 是为嵌入式 server 而生,所以 jfinal undertow 项目是不需要 web.xml 这个文件的 线上这版 Filter.Servelt.Listener.Web ...
- matplotlib等高线图-【老鱼学matplotlib】
等高线图是在地理课中讲述山峰山谷时绘制的图形,在机器学习中也会被用在绘制梯度下降算法的图形中. 因为等高线的图有三个信息:x, y以及x,y所对应的高度值. 这个高度值的计算我们用一个函数来表述: # ...
- Redis 数据结构之dict
上篇文章<Redis数据结构概述>中,了解了常用数据结构.我们知道Redis以高效的方式实现了多种数据结构,因此把Redis看做为数据结构服务器也未尝不可.研究Redis的数据结构和正确. ...
- mysql查看每个数据库所占磁盘大小
#查看每个数据库所占磁盘大小 SELECT TABLE_SCHEMA AS "库名", , ) AS "表所占空间(MB)", , ) AS "索引所 ...
- 课堂小记---html
其他注意点: 行高line-hight的继承特性: 行高有三种属性值:数字(1.5).百分比(150%).长度值(1.5em或者30px).继承上这三者是有区别的. 当属性值为数字值,其子元素会继承行 ...