给定正整数序列x1,..., xn (n<=500)。
(1)计算其最长递增子序列的长度s。
(2)计算从给定的序列中最多可取出多少个长度为s的递增子序列。
(3)如果允许在取出的序列中多次使用x1和xn,则从给定序列中最多可取出多少个长
度为s的递增子序列。

这题求的其实是最长非递减子序列。。

第一问,是个经典的DP,dp[i]表示序列x1...xi且以xi结尾的LIS。

第二问,这么建容量网络:

    • x1...xn中每个i,拆作两点i和i',连<i,i'>容量1的边
    • 源点和所有dp[i]==1的i,连<vs,i>容量1的边
    • 汇点和所有dp[i]==s的i,连<i',vt>容量1的边
    • 对于所有xi<=xj且dp[i]==dp[j]+1的i和j,连<i',j>的容量1的边

  然后其最大流就是答案。

第三问,在第二问基础上把与x1和xn相关的边容量设置成INF跑最大流。另外如果LIS为1,那样直接输出n,不然结果会是INF。

 #include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define INF (1<<30)
#define MAXN 1111
#define MAXM 2222222 struct Edge{
int v,cap,flow,next;
}edge[MAXM];
int vs,vt,NE,NV;
int head[MAXN]; void addEdge(int u,int v,int cap){
edge[NE].v=v; edge[NE].cap=cap; edge[NE].flow=;
edge[NE].next=head[u]; head[u]=NE++;
edge[NE].v=u; edge[NE].cap=; edge[NE].flow=;
edge[NE].next=head[v]; head[v]=NE++;
} int level[MAXN];
int gap[MAXN];
void bfs(){
memset(level,-,sizeof(level));
memset(gap,,sizeof(gap));
level[vt]=;
gap[level[vt]]++;
queue<int> que;
que.push(vt);
while(!que.empty()){
int u=que.front(); que.pop();
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(level[v]!=-) continue;
level[v]=level[u]+;
gap[level[v]]++;
que.push(v);
}
}
} int pre[MAXN];
int cur[MAXN];
int ISAP(){
bfs();
memset(pre,-,sizeof(pre));
memcpy(cur,head,sizeof(head));
int u=pre[vs]=vs,flow=,aug=INF;
gap[]=NV;
while(level[vs]<NV){
bool flag=false;
for(int &i=cur[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap!=edge[i].flow && level[u]==level[v]+){
flag=true;
pre[v]=u;
u=v;
//aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap));
aug=min(aug,edge[i].cap-edge[i].flow);
if(v==vt){
flow+=aug;
for(u=pre[v]; v!=vs; v=u,u=pre[u]){
edge[cur[u]].flow+=aug;
edge[cur[u]^].flow-=aug;
}
//aug=-1;
aug=INF;
}
break;
}
}
if(flag) continue;
int minlevel=NV;
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap!=edge[i].flow && level[v]<minlevel){
minlevel=level[v];
cur[u]=i;
}
}
if(--gap[level[u]]==) break;
level[u]=minlevel+;
gap[level[u]]++;
u=pre[u];
}
return flow;
} int d[],a[];
int main(){
freopen("alis.in","r",stdin);
freopen("alis.out","w",stdout);
int n;
scanf("%d",&n);
for(int i=; i<=n; ++i) scanf("%d",a+i);
int lis=;
for(int i=; i<=n; ++i){
d[i]=;
for(int j=; j<i; ++j){
if(a[j]<=a[i]) d[i]=max(d[i],d[j]+);
}
lis=max(lis,d[i]);
}
printf("%d\n",lis);
if(lis==){
printf("%d\n%d",n,n);
return ;
}
vs=; vt=n<<|; NV=vt+; NE=;
memset(head,-,sizeof(head));
for(int i=; i<=n; ++i){
if(d[i]==) addEdge(vs,i,);
if(d[i]==lis) addEdge(i+n,vt,);
addEdge(i,i+n,);
}
for(int i=; i<n; ++i){
for(int j=i+; j<=n; ++j){
if(a[j]>=a[i] && d[j]==d[i]+) addEdge(i+n,j,);
}
}
printf("%d\n",ISAP());
vs=; vt=n<<|; NV=vt+; NE=;
memset(head,-,sizeof(head));
for(int i=; i<=n; ++i){
if(i== || i==n){
if(d[i]==) addEdge(vs,i,INF);
if(d[i]==lis) addEdge(i+n,vt,INF);
addEdge(i,i+n,INF);
}else{
if(d[i]==) addEdge(vs,i,);
if(d[i]==lis) addEdge(i+n,vt,);
addEdge(i,i+n,);
}
}
for(int i=; i<n; ++i){
for(int j=i+; j<=n; ++j){
if(a[j]>=a[i] && d[j]==d[i]+) addEdge(i+n,j,);
}
}
printf("%d\n",ISAP());
return ;
}

COGS731 [网络流24题] 最长递增子序列(最大流)的更多相关文章

  1. Cogs 731. [网络流24题] 最长递增子序列(最大流)

    [网络流24题] 最长递增子序列 ★★★☆ 输入文件:alis.in 输出文件:alis.out 简单对比 时间限制:1 s 内存限制:128 MB «问题描述: 给定正整数序列x1,-, xn. ( ...

  2. loj6005 [网络流24题]最长递增子序列

    题意:给你一个序列,求不严格上升lcs长度/最多有几个没有重复元素的lcs/如果x1和xn可以多次出现,求最多有几个lcs?n<=500. 标程: #include<cstdio> ...

  3. COGS743. [网络流24题] 最长k可重区间集

    743. [网络流24题] 最长k可重区间集 ★★★   输入文件:interv.in   输出文件:interv.out   简单对比时间限制:1 s   内存限制:128 MB «问题描述: «编 ...

  4. [网络流24题]最长k可重区间集[题解]

    最长 \(k\) 可重区间集 题目大意 给定实心直线 \(L\) 上 \(n\) 个开区间组成的集合 \(I\) ,和一个正整数 \(k\) ,试设计一个算法,从开区间集合 \(I\) 中选取开区间集 ...

  5. LIbreOJ #6011. 「网络流 24 题」运输问题 最小费用最大流

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

  6. [网络流24题] 最长K可重区间集问题

    题目链接:戳我 当时刷24题的时候偷了懒,没有写完,结果落下这道题没有写qwq结果今天考试T3中就有一部分要用到这个思想,蒟蒻我硬是没有想到网络流呜呜呜 最大费用流. 就是我们考虑将问题转化一下,转化 ...

  7. 2018.10.14 loj#6003. 「网络流 24 题」魔术球(最大流)

    传送门 网络流好题. 这道题可以动态建图. 不难想到把每个球iii都拆点成i1i_1i1​和i2i_2i2​,每次连边(s,i1),(i2,t)(s,i_1),(i_2,t)(s,i1​),(i2​, ...

  8. [cogs731] [网络流24题#6] 最长递增子序列 [网络流,最大流]

    [转hzwer]第一问是LIS,动态规划求解,第二问和第三问用网络最大流解决.首先动态规划求出F[i],表示以第i位为开头的最长上升序列的长度,求出最长上升序列长度K.1.把序列每位i拆成两个点< ...

  9. P2766 [网络流24题]最长不下降子序列问题

    ha~ «问题描述: 给定正整数序列$x_1,...,x_n$ .$n<=500$ 求(1)计算其最长不下降子序列的长度$s$. (2)计算从给定的序列中最多可取出多少个长度为$s$的不下降子序 ...

随机推荐

  1. js 判断所有节假日

    // JavaScript Document calendar = new Date(); month = calendar.getMonth(); date = calendar.getDate() ...

  2. 安装 openSUSE Leap 42.1 之后要做的 8 件事

    导读 openSUSE Leap 确实是个巨大的飞跃,它允许用户运行一个和 SUSE Linux 企业版拥有同样基因的发行版.和其它系统一样,为了实现最佳的使用效果,在使用它之前需要做些优化设置. 下 ...

  3. Unity3D占用内存太大的解决方法

    原地址:http://www.cnblogs.com/88999660/archive/2013/03/15/2961663.html 最近网友通过网站搜索Unity3D在手机及其他平台下占用内存太大 ...

  4. Coursera台大机器学习技法课程笔记03-Kernel Support Vector Machine

    这一节讲的是核化的SVM,Andrew Ng的那篇讲义也讲过,讲的也不错. 首先讲的是kernel trick,为了简化将低维特征映射高维特征后的计算,使用了核技巧.讲义中还讲了核函数的判定,即什么样 ...

  5. 连接池 druid(阿里巴巴的框架)

      引用自:http://blog.163.com/hongwei_benbear/blog/static/1183952912013518405588/ 说的是现在最好的连接池   注: 属性跟 d ...

  6. 菜鸟带你飞______DP基础26道水题

    DP 158:11:22 1205:00:00   Overview Problem Status Rank (56) Discuss Current Time: 2015-11-26 19:11:2 ...

  7. Linux Apache 怎么修改工作模式

    Apache默认为prefork模式,主要是考虑到稳定性的原因. 要切换到worker模式,则需要登录到linux上,进行如下操作: 进入/usr/sbin目录 cd /usr/sbin 将当前的pr ...

  8. abstract class和interface的区别

    1. 引言 2. 概念引入 ●什么是接口? 接口是包含一组虚方法的抽象类型,其中每一种方法都有其名称.参数和返回值.接口方法不能包含任何实现,CLR允许接口可以包含事件.属性.索引 器.静态方法.静态 ...

  9. maven3 junit4 spring3 jdk8 :junit一直报错,害的我几个星期都是这个错,你妹的!

    [org.springframework.test.context.junit4.SpringJUnit4ClassRunner]SpringJUnit4ClassRunner constructor ...

  10. python将json格式的数据转换成文本格式的数据或sql文件

    python如何将json格式的数据快速的转化成指定格式的数据呢?或者转换成sql文件? 下面的例子是将json格式的数据准换成以#_#分割的文本数据,也可用于生成sql文件. [root@bogon ...