题目描述

«问题描述:

给定正整数序列x1,...,xn 。

(1)计算其最长不下降子序列的长度s。

(2)计算从给定的序列中最多可取出多少个长度为s的不下降子序列。

(3)如果允许在取出的序列中多次使用x1和xn,则从给定序列中最多可取出多少个长度为s的不下降子序列。

«编程任务:

设计有效算法完成(1)(2)(3)提出的计算任务。

输入格式

第1 行有1个正整数n,表示给定序列的长度。接下来的1 行有n个正整数n:x1, ..., xn。

输出格式

第1 行是最长不下降子序列的长度s。第2行是可取出的长度为s 的不下降子序列个数。第3行是允许在取出的序列中多次使用x1和xn时可取出的长度为s 的不下降子序列个数。

输入输出样例

输入
4  
3 6 2 5
输出 
2
2
3

说明/提示

n≤500

解析

() n^的dp  求出S

()从源点向dp[i]=1的点连一条容量为1的边,dp[i]=S的点向汇点连一条容量为1的边。

    因为每个点只能用一次,所以我们还要把一个点拆成两个i 和 i+n,在它们之间连一条容量为1的边。

    之后n^枚举每两个点,若两个点i,j满足a[j]<=a[i]且dp[i]=dp[j]+,则在i+n,j之间连一条容量为1的边。

    建好图后跑一边最大流,就是第二问的答案。

()将源点向dp[i]=1的点连的边的容量改为inf,dp[i]=1的点与拆出来的点边权也要设为inf。同理汇点也一样。 

代码

// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+,mod=1e9+,inf=0x3f3f3f3f;
typedef long long ll;
struct edge
{
int from,to,c,f;
edge(int u,int v,int c,int f):from(u),to(v),c(c),f(f) {}
};
int n,m;
vector<edge> edges;
vector<int> g[maxn];
int d[maxn];//从起点到i的距离
int cur[maxn];//当前弧下标
void init(int N)
{
for(int i=; i<=N; i++) g[i].clear();
edges.clear();
}
void addedge(int from,int to,int c) //加边 支持重边
{
edges.push_back(edge(from,to,c,));
edges.push_back(edge(to,from,,));
int siz=edges.size();
g[from].push_back(siz-);
g[to].push_back(siz-);
}
int bfs(int s,int t) //构造一次层次图
{
memset(d,-,sizeof(d));
queue<int> q;
q.push(s);
d[s]=;
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=;i<g[x].size();i++)
{
edge &e=edges[g[x][i]];
if(d[e.to]<&&e.f<e.c) //d[e.to]=-1表示没访问过
{
d[e.to]=d[x]+;
q.push(e.to);
}
}
}
return d[t];
}
int dfs(int x,int a,int t) // a表示x点能接收的量
{
if(x==t||a==)return a;
int flow=,f;//flow总的增量 f一条增广路的增量
for(int &i=cur[x];i<g[x].size();i++)//cur[i] &引用修改其值 从上次考虑的弧
{
edge &e=edges[g[x][i]];
if(d[x]+==d[e.to]&&(f=dfs(e.to,min(a,e.c-e.f),t))>) //按照层次图增广 满足容量限制
{
e.f+=f;
edges[g[x][i]^].f-=f; //修改流量
flow+=f;
a-=f;
if(a==) break;
}
}
return flow;
}
int maxflow(int s,int t)
{
int flow=;
while(bfs(s,t)!=-) //等于-1代表构造层次图失败 结束
{
memset(cur,,sizeof(cur));
flow+=dfs(s,inf,t);
}
return flow;
}
int a[],dp[];
int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
int maxdp=;
for(int i=;i<=n;i++){
dp[i]=;
for(int j=;j<i;j++){
if(a[j]<=a[i])
dp[i]=max(dp[i],dp[j]+);
}
maxdp=max(maxdp,dp[i]);
}
printf("%d\n",maxdp);
if(maxdp==){
printf("%d\n%d\n",n,n);
continue;
}
init(*n+);
for(int i=;i<=n;i++){
if(dp[i]==) addedge(,i,);
if(dp[i]==maxdp) addedge(i+n,*n+,);
addedge(i,i+n,);
for(int j=;j<i;j++){
if(a[j]<=a[i]&&dp[i]==dp[j]+)
addedge(j+n,i,);
}
}
printf("%d\n",maxflow(,*n+));
init(*n+);
for(int i=;i<=n;i++){
if(dp[i]==)addedge(,i,inf);
if(dp[i]==maxdp) addedge(i+n,*n+,inf);
if(dp[i]==||dp[i]==maxdp)addedge(i,i+n,inf);
else addedge(i,i+n,);
for(int j=;j<i;j++){
if(a[j]<=a[i]&&dp[i]==dp[j]+)
addedge(j+n,i,);
}
}
printf("%d\n",maxflow(,*n+));
}
}

网络流24题 P2766 最长不下降子序列问题的更多相关文章

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

    网络流二十四题 网络流是个好东西,希望我也会. 网络流?\(orz\ zsy!!!!!\) P2766 最长不下降子序列问题 考虑我们是如何\(dp\)这个\(LIS\)的. 我们是倒着推,设置\(d ...

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

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

  3. 【网络流24题】最长k可重线段集(费用流)

    [网络流24题]最长k可重线段集(费用流) 题面 Cogs的数据有问题 Loj 洛谷 题解 这道题和最长k可重区间集没有区别 只不过费用额外计算一下 但是,还是有一点要注意的地方 这里可以是一条垂直的 ...

  4. 【网络流24题】最长k可重区间集(费用流)

    [网络流24题]最长k可重区间集(费用流) 题面 Cogs Loj 洛谷 题解 首先注意一下 这道题目里面 在Cogs上直接做就行了 洛谷和Loj上需要判断数据合法,如果\(l>r\)就要交换\ ...

  5. LibreOJ #6014. 「网络流 24 题」最长 k 可重区间集

    #6014. 「网络流 24 题」最长 k 可重区间集 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   ...

  6. 【刷题】LOJ 6227 「网络流 24 题」最长k可重线段集问题

    题目描述 给定平面 \(\text{xoy}\) 上 \(n\) 个开线段组成的集合 \(\text{I}\) ,和一个正整数 \(k\) ,试设计一个算法. 从开线段集合 \(\text{I}\) ...

  7. loj #6014. 「网络流 24 题」最长 k 可重区间集

    #6014. 「网络流 24 题」最长 k 可重区间集 题目描述 给定实直线 L LL 上 n nn 个开区间组成的集合 I II,和一个正整数 k kk,试设计一个算法,从开区间集合 I II 中选 ...

  8. 【网络流24题】最长k可重区间集问题(费用流)

    [网络流24题]最长k可重区间集问题 [问题分析] 最大权不相交路径问题,可以用最大费用最大流解决. [建模方法] 方法1 按左端点排序所有区间,把每个区间拆分看做两个顶点<i.a>< ...

  9. P2766 最长不下降子序列问题 网络流重温

    P2766 最长不下降子序列问题 这个题目还是比较简单的,第一问就是LIS 第二问和第三问都是网络流. 第二问要怎么用网络流写呢,首先,每一个只能用一次,所以要拆点. 其次,我们求的是长度为s的不下降 ...

随机推荐

  1. js 监听键盘的enter键

    // js 版本 window.onload=function(){ document.onkeydown=function(ev){ var event=ev ||event if(event.ke ...

  2. VMware Workstation虚拟机安装

    VMware Workstation虚拟机安装 我们缺乏资金, 所以吃土.我们想搭 hadoop 集群, redis 集群, k8s 集群, 怎么办? 用虚拟机!! 一. 安装普通版本(Worksta ...

  3. 解决tensorflow 调用bug Running model failed:Invalid argument: NodeDef mentions attr 'dilations' not in Op<name=Conv2D; signature=input:T, filter:T ->

    将tensorflow C++ 版本更新为何训练版本一致即可

  4. form-create教程:给内置组件和自定义组件添加事件

    本文将介绍form-create如何给内置组件和自定义组件添加事件 form-create 是一个可以通过 JSON 生成具有动态渲染.数据收集.验证和提交功能的表单生成器.并且支持生成任何 Vue ...

  5. Java中程序、进程、线程的区别。

    程序.进程.线程的区别. 程序(program):是一个指令的集合.程序不能独立执行,只有被加载到内存中,系统为他分配资源后才能执行. 进程(process):一个执行中的程序称为进程. 进程是系统分 ...

  6. java入门学习总结_03

    1.键盘录入 2.分支结构 键盘录入 概述 1.键盘录入:在程序运行的过程中,可以让用户录入一些数据,存储在内存的变量中,在后续的程序运行过程中,可以使用这些数据. 2.步骤: 第一步:导包,在类声明 ...

  7. 使用SQLAlchemy,以及问题处理

    https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0014021031294178 ...

  8. MySQL读写分离高可用集群及读操作负载均衡(Centos7)

    目录 概述 keepalived和heartbeat对比 一.环境 二.部署 部署lvs代理和keepalived MySQL+heartbeat+drbd的部署 MySQL主从复制 web服务器及a ...

  9. 个人推荐-几款好用的App

    前言 在使用智能手机的过程中比较喜欢尝试一些新奇好玩的app,同时也积攒下了不少个人认为很有帮助或很有特点的app,写这篇随笔当做一个记录吧. 便签-小周便签 一款功能十分强大的便签app,在编辑界面 ...

  10. WebMvcConfig

    package cn.xx.yy; import java.util.ArrayList;import java.util.HashMap;import java.util.List;import j ...