COGS731 [网络流24题] 最长递增子序列(最大流)
给定正整数序列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题] 最长递增子序列(最大流)的更多相关文章
- Cogs 731. [网络流24题] 最长递增子序列(最大流)
[网络流24题] 最长递增子序列 ★★★☆ 输入文件:alis.in 输出文件:alis.out 简单对比 时间限制:1 s 内存限制:128 MB «问题描述: 给定正整数序列x1,-, xn. ( ...
- loj6005 [网络流24题]最长递增子序列
题意:给你一个序列,求不严格上升lcs长度/最多有几个没有重复元素的lcs/如果x1和xn可以多次出现,求最多有几个lcs?n<=500. 标程: #include<cstdio> ...
- COGS743. [网络流24题] 最长k可重区间集
743. [网络流24题] 最长k可重区间集 ★★★ 输入文件:interv.in 输出文件:interv.out 简单对比时间限制:1 s 内存限制:128 MB «问题描述: «编 ...
- [网络流24题]最长k可重区间集[题解]
最长 \(k\) 可重区间集 题目大意 给定实心直线 \(L\) 上 \(n\) 个开区间组成的集合 \(I\) ,和一个正整数 \(k\) ,试设计一个算法,从开区间集合 \(I\) 中选取开区间集 ...
- LIbreOJ #6011. 「网络流 24 题」运输问题 最小费用最大流
#6011. 「网络流 24 题」运输问题 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 ...
- [网络流24题] 最长K可重区间集问题
题目链接:戳我 当时刷24题的时候偷了懒,没有写完,结果落下这道题没有写qwq结果今天考试T3中就有一部分要用到这个思想,蒟蒻我硬是没有想到网络流呜呜呜 最大费用流. 就是我们考虑将问题转化一下,转化 ...
- 2018.10.14 loj#6003. 「网络流 24 题」魔术球(最大流)
传送门 网络流好题. 这道题可以动态建图. 不难想到把每个球iii都拆点成i1i_1i1和i2i_2i2,每次连边(s,i1),(i2,t)(s,i_1),(i_2,t)(s,i1),(i2, ...
- [cogs731] [网络流24题#6] 最长递增子序列 [网络流,最大流]
[转hzwer]第一问是LIS,动态规划求解,第二问和第三问用网络最大流解决.首先动态规划求出F[i],表示以第i位为开头的最长上升序列的长度,求出最长上升序列长度K.1.把序列每位i拆成两个点< ...
- P2766 [网络流24题]最长不下降子序列问题
ha~ «问题描述: 给定正整数序列$x_1,...,x_n$ .$n<=500$ 求(1)计算其最长不下降子序列的长度$s$. (2)计算从给定的序列中最多可取出多少个长度为$s$的不下降子序 ...
随机推荐
- CocoStudio基础教程(5)使用CocoStudio场景编辑器关联组件
1.概述 我们有了UI交互.有了动画人物.有了物理模拟,还差最后一步——将这些元素融合起来.这就要用到cocoStudio中的场景编辑器了.这次我们要将先前我们做过的所有东西都放到一个场景中去.这项工 ...
- cocos2d-x类型转换(CCstring int string char UTF-8互转)
在做数据转换时,最好包含以下头文件 #include <iostream> #include <cmath> #include <string> #include ...
- django-cms 代码研究(一)djangocms是什么
首先用djangocms生成了一个站点(具体参考这里:http://www.cnblogs.com/Tommy-Yu/p/3878488.html),其文件结构如下: 本来以为会很有逼格,结果一看傻眼 ...
- PeopleEditor允许客户端输入的同时验证输入的内容
如何判断PeopleEditor的值为空 在sharepoint开发中,我们经常会用到PeopleEditor这一控件,最近我在写程序的时候用到了,开始的时候不知道怎么用,后来问题解决啦,现在写出 ...
- C++ virtual descructor
[代码1] C++ Code 12345678910111213141516171819202122232425262728293031323334353637383940414243444546 ...
- Java for LeetCode 044 Wildcard Matching
Implement wildcard pattern matching with support for '?' and '*'. '?' Matches any single character. ...
- JavaScript设计模式 - 代理模式
代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问 代理模式的用处(个人理解):为了保障当前对象的单一职责(相对独立性),而需要创建另一个对象来处理调用当前对象之前的一些逻辑以提高代码的效 ...
- javascript十六进制数字和ASCII字符之间转换
var hex="0x29";//十六进制 var charValue = String.fromCharCode(hex);//生成Unicode字符 var charCode ...
- java 格式化时间
java.text.DateFormat format1 = new java.text.SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); form ...
- eclipse4.4 tomcat jrebel使用
1.下载jrebel破解包 2.去eclipse -->Help -->EclipseMarketplace 下载eclipse jrebel 也可以下载离线安装包,然后eclipse - ...