传送门

题解来自网络流24题:

【问题分析】

第一问时LIS,动态规划求解,第二问和第三问用网络最大流解决。

【建模方法】

首先动态规划求出F[i],表示以第i位为开头的最长上升序列的长度,求出最长上升序列长度K。

1、把序列每位i拆成两个点<i.a>和<i.b>,从<i.a>到<i.b>连接一条容量为1的有向边。

2、建立附加源S和汇T,如果序列第i位有F[i]=K,从S到<i.a>连接一条容量为1的有向边。

3、如果F[i]=1,从<i.b>到T连接一条容量为1的有向边。

4、如果j>i且A[i] < A[j]且F[j]+1=F[i],从<i.b>到<j.a>连接一条容量为1的有向边。

求网络最大流,就是第二问的结果。把边(<1.a>,<1.b>)(<N.a>,<N.b>)(S,<1.a>)(<N.b>,T)这四条边的容量修改为无穷大,再求一次网络最大流,就是第三问结果。

【建模分析】

上述建模方法是应用了一种分层图的思想,把图每个顶点i按照F[i]的不同分为了若干层,这样图中从S出发到T的任何一条路径都是一个满足条件的最长上升子序列。

由于序列中每个点要不可重复地取出,需要把每个点拆分成两个点。单位网络的最大流就是增广路的条数,所以最大流量就是第二问结果。

第三问特殊地要求x1和xn可以重复使用,只需取消这两个点相关边的流量限制,求网络最大流即可。

还有这个题题意有些问题,不是递增,是不递减。

——代码

 #include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#define N 2020
#define M 3000001
#define max(x, y) ((x) > (y) ? (x) : (y))
#define min(x, y) ((x) < (y) ? (x) : (y)) int n, ans, cnt, s, t, sum;
int a[N], f[N];
int head[N], to[M], val[M], next[M], dis[N], cur[N]; inline int read()
{
int x = , f = ;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -;
for(; isdigit(ch); ch = getchar()) x = (x << ) + (x << ) + ch - '';
return x * f;
} inline void add(int x, int y, int z)
{
to[cnt] = y;
val[cnt] = z;
next[cnt] = head[x];
head[x] = cnt++;
} inline bool bfs()
{
int i, u, v;
std::queue <int> q;
memset(dis, -, sizeof(dis));
q.push(s);
dis[s] = ;
while(!q.empty())
{
u = q.front(), q.pop();
for(i = head[u]; i ^ -; i = next[i])
{
v = to[i];
if(val[i] && dis[v] == -)
{
dis[v] = dis[u] + ;
if(v == t) return ;
q.push(v);
}
}
}
return ;
} inline int dfs(int u, int maxflow)
{
if(u == t) return maxflow;
int i, v, d, ret = ;
for(i = cur[u]; i ^ -; i = next[i])
{
v = to[i];
if(val[i] && dis[v] == dis[u] + )
{
d = dfs(v, min(val[i], maxflow - ret));
ret += d;
cur[u] = i;
val[i] -= d;
val[i ^ ] += d;
if(ret == maxflow) return ret;
}
}
return ret;
} inline void clear()
{
int i, j;
sum = cnt = ;
memset(head, -, sizeof(head));
for(i = ; i <= n; i++)
{
add(i, i + n, ), add(i + n, i, );
if(f[i] == ) add(s, i, ), add(i, s, );
if(f[i] == ans) add(i + n, t, ), add(t, i + n, );
}
for(i = ; i <= n; i++)
for(j = ; j < i; j++)
if(a[j] <= a[i] && f[j] + == f[i])
add(j + n, i, ), add(i, j + n, );
} int main()
{
int i, j, x;
n = read();
s = , t = (n << ) + ;
for(i = ; i <= n; i++)
{
a[i] = read();
x = ;
for(j = ; j < i; j++)
if(a[j] <= a[i])
x = max(x, f[j]);
f[i] = x + ;
ans = max(ans, f[i]);
}
printf("%d\n", ans);
clear();
while(bfs())
{
for(i = s; i <= t; i++) cur[i] = head[i];
sum += dfs(s, 1e9);
}
printf("%d\n", sum);
clear();
add(s, , 1e9), add(, s, );
add(, + n, 1e9), add( + n, , );
if(f[n] == ans)
{
add(n << , t, 1e9), add(t, n << , );
add(n, n << , 1e9), add(n << , n, );
}
while(bfs())
{
for(i = s; i <= t; i++) cur[i] = head[i];
sum += dfs(s, 1e9);
}
printf("%d\n", sum);
return ;
}

[luoguP2766] 最长递增子序列问题(最大流)的更多相关文章

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

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

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

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

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

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

  4. 【刷题】LOJ 6005 「网络流 24 题」最长递增子序列

    题目描述 给定正整数序列 \(x_1 \sim x_n\) ,以下递增子序列均为非严格递增. 计算其最长递增子序列的长度 \(s\) . 计算从给定的序列中最多可取出多少个长度为 \(s\) 的递增子 ...

  5. (转载)最长递增子序列 O(NlogN)算法

    原博文:传送门 最长递增子序列(Longest Increasing Subsequence) 下面我们简记为 LIS. 定义d[k]:长度为k的上升子序列的最末元素,若有多个长度为k的上升子序列,则 ...

  6. 最长公共子序列(LCS)和最长递增子序列(LIS)的求解

    一.最长公共子序列 经典的动态规划问题,大概的陈述如下: 给定两个序列a1,a2,a3,a4,a5,a6......和b1,b2,b3,b4,b5,b6.......,要求这样的序列使得c同时是这两个 ...

  7. 最长递增子序列 O(NlogN)算法

    转自:点击打开链接 最长递增子序列,Longest Increasing Subsequence 下面我们简记为 LIS. 排序+LCS算法 以及 DP算法就忽略了,这两个太容易理解了. 假设存在一个 ...

  8. 51nod 1134 最长递增子序列

    题目链接:51nod 1134 最长递增子序列 #include<cstdio> #include<cstring> #include<algorithm> usi ...

  9. 动态规划 - 最长递增子序列(LIS)

    最长递增子序列是动态规划中经典的问题,详细如下: 在一个已知的序列{a1,a2,...,an}中,取出若干数组组成新的序列{ai1,ai2,...,aim},其中下标i1,i2,...,im保持递增, ...

随机推荐

  1. (六)VMware Harbor简单使用

    VMware Harbor简单使用 1. 登陆: [用户:admin  , 密码:Harbor12345]配置文件里设置的 登陆后的界面: 2. 用户管理: 2.1 新近用户 3. 仓库管理: 3.1 ...

  2. angular设置反向代理

    本地调试,需要用到服务器的api,发现chrome安全问题,需要解决跨域问题.现给出解决方案: 1.增加proxy.conf.json文件 位置与package.json文件同级(可指定) 2.pac ...

  3. javaweb基础(5)_servlet原理

    一.Servlet简介 Servlet是sun公司提供的一门用于开发动态web资源的技术. Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个Java程序向 ...

  4. Bootstrap历练实例:嵌套的媒体对象

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  5. MarkdownPad 2 Pro 注册码

    MarkdownPad 2 Pro 注册码 MarkdownPad 是 Windows 平台上一个功能完善的 Markdown 编辑器. 提供了语法高亮和方便的快捷键功能,给您最好的 Markdown ...

  6. iOS开发之WIFI,3G/4G两种网络同时使用技巧

    最近遇到一个比较奇葩的需求:App与硬件通过WiFi LAN通信, 同时App需要与服务器通过3G/4G WAN通信,如下图: 众所周知,手机同时打开WiFi和3G时候,会优先走WiFi.这个该如何实 ...

  7. ARC中__weak;__strong;__unsafe_unretained;修饰词

    测试代码: // Human.h代码 @interface Human : NSObject @property (nonatomic, weak) Cat *pinkCat; @property ( ...

  8. NSOperation、NSOperationQueue

    NSOperation.NSOperationQueue NSOperation 和 NSOperationQueue 配合使用也能实现多线程. NSOperation 继承于 NSObject,是一 ...

  9. JS - Array.prototype.sort(compare)

    function compare(a, b) { return -1; // a 在 b 前面 return 1; // a 在 b 后面 return 0; // 并列排序,保持在源数组中的先后顺序 ...

  10. mysql的字符串连接符

    以前用SQL Server 连接字符串是用“+”,现在数据库用mysql,写个累加两个字段值SQL语句居然不支持"+",郁闷了半天在网上查下,才知道mysql里的+是数字相加的操作 ...