题目链接: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+网络流]的更多相关文章

  1. 【题解】Luogu P2766 最长不下降子序列问题

    原题传送门 实际还是比较套路的建图 先暴力dp一下反正数据很小 第一小问的答案即珂以求出数列的最长不下降子序列的长度s 考虑第二问如何做: 将每个点拆点 从前向后连一条流量为1的边 如果以它为终点的最 ...

  2. 最长不下降子序列(LIS)

    最长上升子序列.最长不下降子序列,解法差不多,就一点等于不等于的差别,我这里说最长不下降子序列的. 有两种解法. 一种是DP,很容易想到,就这样: REP(i,n) { f[i]=; FOR(j,,i ...

  3. 动态规划——最长不下降子序列(LIS)

    最长不降子序列是这样一个问题: 下面介绍动态规划的做法. 令 dp[i] 表示以 A[i] 结尾的最长不下降序列长度.这样对 A[i] 来说就会有两种可能: 如果存在 A[i] 之前的元素 A[j] ...

  4. 最长不下降子序列(线段树优化dp)

    最长不下降子序列 题目大意: 给定一个长度为 N 的整数序列:A\(_{1}\),A\(_{2}\),⋅⋅⋅,A\(_{N}\). 现在你有一次机会,将其中连续的 K 个数修改成任意一个相同值. 请你 ...

  5. luogu P2766 最长不下降子序列问题

    第一问可以直接DP来做,联想上一题,线性规划都可以化为网络流?我们可以借助第一问的DP数组,来建立第二问第三问的网络流图,考虑每一种可能,都是dp数组中满足num[i]>=num[j]& ...

  6. [Swust OJ 585]--倒金字塔(LIS最长不下降子序列)

    题目链接:http://acm.swust.edu.cn/problem/585/ Time limit(ms): 3000 Memory limit(kb): 65535   SWUST国的一支科学 ...

  7. luogu2766 最长不下降子序列问题

    第一问DP水过.dp[i]代表以i结尾的最长不下降子序列长度. 二三问网络流. 第二问是说每个子序列不能重复使用某个数字. 把每个点拆成p(i),q(i).连边. 要是dp[i]=1,连源,p(i) ...

  8. Libre 6005 「网络流 24 题」最长递增子序列 / Luogu 2766 最长递增子序列问题(网络流,最大流)

    Libre 6005 「网络流 24 题」最长递增子序列 / Luogu 2766 最长递增子序列问题(网络流,最大流) Description 问题描述: 给定正整数序列x1,...,xn . (1 ...

  9. Luogu 1020 导弹拦截(动态规划,最长不下降子序列,二分,STL运用,贪心,单调队列)

    Luogu 1020 导弹拦截(动态规划,最长不下降子序列,二分,STL运用,贪心,单调队列) Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺 ...

随机推荐

  1. vlan 知识学习

    背景     有人反映打印机总是提示ip冲突,经检查,打印机虽然设置了固定ip,但是所有员工在路由器都是设置了DHCP,所以会存在员工占用打印机IP 情况,在路由器添加某一段的ip不自动分配解决此问题 ...

  2. Beta冲刺(1/7)

    目录 摘要 团队部分 个人部分 摘要 队名:小白吃 组长博客:hjj 作业博客:beta冲刺(1/7) 团队部分 后敬甲(组长) 过去两天完成了哪些任务 团队完成测试答辩 整理博客 复习接口 接下来的 ...

  3. 手把手教你写vue插件并发布(一)

    vue的插件开发 这篇文章较长,需要一定的阅读时间.这里有一份改善版本的插件笔记,在一个项目下完成开发.测试.发布的全过程.https://www.cnblogs.com/adouwt/p/96555 ...

  4. 使用Jmeter监测服务器性能指标

    jmeter监控服务器CPU.内存等性能参数,需要安装一些插件 插件名:JMeterPlugins-Extras,JMeterPlugins-Standard 以及ServerAgent. 下载地址: ...

  5. django 实战篇之模板层

    模板层 ​ {{}} 变量相关 ​ {%%} 逻辑相关 ​ 前端获取容器类型的数据统一使用 句点符(.) ​ 两种给模板传递值的方式 return render(request,'index.html ...

  6. Zabbix告警发送邮件时附带性能图

    脚本处理逻辑分析: 通过zabbix传递给脚本的message参数,筛选出报警信息的itemid; 通过itemid获取到图片并保存; 将报警信息和图片组装成html; 发送邮件. 后续脚本里面的处理 ...

  7. 关于Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/springmvc-demo-01-start]]出错的解决方法

    出错的详情: 严重: A child container failed during start java.util.concurrent.ExecutionException: org.apache ...

  8. thinkphp微信浏览器内拉起微信支付

    vendor/wxpay/pay.php <?php /* +-----------------------------------+ | 微信支付类 | +------------------ ...

  9. html 转 PDF wkhtmltopdf image 不能显示的问题

    把src的路径修改为本地路径 就可以,如 <img src="file:///C:\a.jpg">

  10. SQL反模式学习笔记18 减少SQL查询数据,避免使用一条SQL语句解决复杂问题

    目标:减少SQL查询数据,避免使用一条SQL语句解决复杂问题 反模式:视图使用一步操作,单个SQL语句解决复杂问题 使用一个查询来获得所有结果的最常见后果就是产生了一个笛卡尔积.导致查询性能降低. 如 ...