【网络流24题】最长不下降子序列(最大流,动态规划)
2018-01-03 21:40
399 查看
题面
Cogs题解
很有趣的一道题目尽管我自己还是有一些懵逼
第一问,直接大力DP一下,不解释了
第二问,考虑到一个长度为ans的子序列的开头
他的dp值一定等于ans,
所以,如果一个点的dp值为ans,就从源点连过去,容量为1
因为每个数只能用一次,因此拆点
自己向自己的新点连容量为1的边
一个子序列的结束的位置其dp值必定为1
所以从dp值为1的新点向汇点连边,容量为1
接下来考虑点与点之间的关系
如果dp[i]=dp[j]+1 并且 a[i]<=a[j]
很显然的,这两个点可以连在一起
因为是一条路径,所以流要回到一侧继续寻找
所以从j’连向i
第一问就这样跑最大流
第二问,因为1和n无限制
所以,如果1和n满足值开头或者结尾的条件的话
就把从源点或者汇点以及连向自己拆出来的点的边的容量改为INF即可
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<set> #include<map> #include<vector> #include<queue> using namespace std; #define MAX 20000 #define MAXL 500000 #define INF 1000000000 inline int read() { int x=0,t=1;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=-1,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return x*t; } struct Line { int v,next,w; }e[MAXL]; int h[MAX],cnt; int S,T,n,m,K,ans,f[MAX],a[MAX],ret; inline void Add(int u,int v,int w) { e[cnt]=(Line){v,h[u],w}; h[u]=cnt++; e[cnt]=(Line){u,h[v],0}; h[v]=cnt++; } int level[MAX]; bool BFS() { memset(level,0,sizeof(level)); level[S]=1; queue<int> Q; Q.push(S); while(!Q.empty()) { int u=Q.front();Q.pop(); for(int i=h[u];i!=-1;i=e[i].next) { int v=e[i].v; if(e[i].w&&!level[v]) level[v]=level[u]+1,Q.push(v); } } return level[T]; } int DFS(int u,int flow) { if(flow==0||u==T)return flow; int ret=0; for(int i=h[u];i!=-1;i=e[i].next) { int v=e[i].v; if(e[i].w&&level[v]==level[u]+1) { int dd=DFS(v,min(flow,e[i].w)); flow-=dd;ret+=dd; e[i].w-=dd;e[i^1].w+=dd; } } return ret; } int Dinic() { //int ret=0; while(BFS())ret+=DFS(S,INF); return ret; } void DP() { for(int i=n;i;i--) { f[i]=1; for(int j=i+1;j<=n;++j) if(a[j]>=a[i]) f[i]=max(f[i],f[j]+1); } for(int i=1;i<=n;++i)ans=max(ans,f[i]); printf("%d\n",ans); } int main() { freopen("alis.in","r",stdin); freopen("alis.out","w",stdout); n=read(); for(int i=1;i<=n;++i)a[i]=read(); DP(); S=0;T=n+n+1; memset(h,-1,sizeof(h));cnt=0; for(int i=1;i<=n;++i)Add(i,i+n,1); for(int i=1;i<=n;++i)if(f[i]==ans)Add(S,i,1); for(int i=1;i<=n;++i)if(f[i]==1)Add(i+n,T,1); for(int i=1;i<=n;++i) for(int j=i+1;j<=n;++j) if(a[i]<=a[j]&&f[j]==f[i]-1)Add(i+n,j,1); printf("%d\n",Dinic()); if(f[1]==ans)Add(S,1,INF),Add(1,1+n,INF); Add(n,n+n,INF);Add(n+n,T,INF); printf("%d\n",Dinic()); return 0; }
相关文章推荐
- 【网络流24题】最长不下降子序列问题
- 【网络流24题】 No.6 最长不减子序列问题 (最大流)[模型:最多不相交路径]
- Libre 6005 「网络流 24 题」最长递增子序列 / Luogu 2766 最长递增子序列问题(网络流,最大流)
- [网络流24题] 最长递增子序列 (最多不相交路径---网络最大流)
- 洛谷2766:[网络流24题]最长不下降子序列问题——题解
- 动态规划实现最大连续子序列和,最长不下降子序列和最长公共子序列
- 【C】动态规划--最大连续子序列和/最长不下降子序列/最长公共子序列/最长回文子串/DAG最长路
- 求最长不下降序列(动态规划)
- hdu1160 FatMouse's Speed 最长下降子序列 动态规划
- 递增子序列最大和(最长递增子序列) 动态规划
- (2)最长不下降子序列问题____动态规划
- [网络流24题][codevs1906]最长递增子序列(dp+isap)
- [网络流24题]最长递增子序列问题 最大流
- 动态规划——最大子序列、最长递增子序列、最长公共子串、最长公共子序列、字符串最小编辑距离日记整理
- 洛谷P2766最长不下降子序列问题(网络流24题)
- tyvj 1208 最长不下降子序列2 求序列b1,b2,b3,…,bm中所有长度(n)最大上升子序列的个数
- 「网络流24题」最长不下降子序列问题
- 最大子序列、最长连续公共子串(连续)、最长公共子序列(动态规划)
- 【网络流24题】No.21 (最长 k 可重区间集问题 最长不相交路径 最大费用流)
- 洛谷P2766 最长不下降子序列问题(最大流)