题目链接: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. python中的赋值操作

    参考:https://www.cnblogs.com/andywenzhi/p/7453374.html?tdsourcetag=s_pcqq_aiomsg(写的蛮好) python中的赋值操作“=” ...

  2. EF的三种数据加载方式

    EF的关联实体加载有三种方式:Lazy Loading,Eager Loading,Explicit Loading,其中Lazy Loading和Explicit Loading都是延迟加载. (一 ...

  3. MySQL问题汇总

    1.中文乱码 连接设置: 数据库设置:

  4. vue 动态变量值不变化

    caseData = { lists:[] }; vm = new Vue({ el: '.hs-mt', data: caseData }); function getlist(pid,id){ $ ...

  5. 18 常用模块 random shutil shevle logging sys.stdin/out/err

    random:随机数 (0, 1) 小数:random.random() ***[1, 10] 整数:random.randint(1, 10) *****[1, 10) 整数:random.rand ...

  6. Axis接口

    Axis支持三种web service的部署和开发,分别为: 1.Dynamic Invocation Interface ( DII) 2.Dynamic Proxy方式 3.Stubs方式Dyna ...

  7. unity读取txt,并且生成vector3的数组

    读取txt的脚本: public void ReadFileTX(){ var str = File.ReadAllText(Application.streamingAssetsPath + &qu ...

  8. Spring 框架

    一. Spring入门 Spring模块都打包成JAR文件,其命名格式如下: spring-maluleName-x.y.z.RELEASE.jar 其中module name是模块的名字,而x.y. ...

  9. Java Spring Boot VS .NetCore (七) 配置文件

    Java Spring Boot VS .NetCore (一)来一个简单的 Hello World Java Spring Boot VS .NetCore (二)实现一个过滤器Filter Jav ...

  10. IntelliJ IDEA 使提示不区分大小写

    File ==> Settings ==> Editor ==> General ==> Code Completion 第一行 Match case 将默认勾选去掉