网络流 之 P2766 最长不下降子序列问题
题目描述
«问题描述:
给定正整数序列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 的不下降子序列个数。
输入输出样例
说明
500n≤500
最长不下降子序列
这个题目第一问显然是LIS
第二问和第三问就转化成最大流。
转化过程(理解了好久)
第二问:
建图,先求出f数组,f[i]表示到第i为的最长的不下降子序列,
然后因为第二问每一个数只能用一次,所以就把一个点拆成一个入点一个出点。
建图就是让f[i]==1的和s连在一起,f[i]==ans的和t连在一起,然后中间如果有
a[i]>=a[j]&&i>j&&f[i]=f[j]+1 这样的话就把 j 的出点和 i 的入点连在一起,这个就是建图过程。
接下来说说为什么这么建图,
首先只考虑第二问,因为每一个点只能用一次,所以就把点拆开,并且权值为1 ,然后因为只有f[i]==1
才会和s点相连,设f[i]==1的个数为x,所以这个就说明最多只能有x个答案,在这个基础上再看有没有从这个
点出发可以到达f[i]==ans的。
接下来说说为什么会 a[i]>=a[j]&&i>j&&f[i]=f[j]+1 这个j的出点和i的入点连在一起。
这个必须是这样子写的,因为只有这个样子到f[i]==ans 的过程中把中间的数字标记一次,不让别的再跑了。
例如说样例: 3 6 2 5 这个ans=2 第二问答案有两组就是 3 6 和 2 5,
3和2都与源点连起来了,6和5 都和汇点连起来了,3也会和6 5 连起来,2就只会和6 连起来,
然后这个答案可以是3 5 或者2 6 和2 5 ,很显然后面的才是最大流。
然后第三问 首先你要看清楚题目,题目说的只是x1和xn可以用无数多次,
所以这个就只要改成 s 到1 和1到n+1 和 n到 n+n if(f[n]==ans) n到 t 这些边改成无数次然后就再跑一次。
因为f[i]==1所以从s到1很有可能会跑很多次,所以,这个既然x1可以用无数多次,则要设s到1和1到1+n为无数多次
如果f[n]!=ans 则说明这个点不会和t连在一起,所以就不能连n到t,但是n到n+n可以连无数多次,不过好像没什么用。
因为n是最后一个
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <string>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 1e5;
int s, t;
struct node
{
int from, to, cap, flow;
node(int from=,int to=,int cap=,int flow=):from(from),to(to),cap(cap),flow(flow){}
};
vector<node>e;
vector<int>G[maxn];
void add(int u,int v,int w)
{
e.push_back(node(u, v, w, ));
e.push_back(node(v, u, , ));
int m = e.size();
G[u].push_back(m - );
G[v].push_back(m - );
}
int a[maxn], dp[maxn];
int level[maxn], iter[maxn]; void bfs(int s)
{
memset(level, -, sizeof(level));
level[s] = ;
queue<int>que;
que.push(s);
while(!que.empty())
{
int u = que.front(); que.pop();
for(int i=;i<G[u].size();i++)
{
node &now = e[G[u][i]];
if(now.cap>now.flow&&level[now.to]<)
{
level[now.to] = level[u] + ;
que.push(now.to);
}
}
}
} int dfs(int u,int v,int f)
{
if (u == v) return f;
for(int &i=iter[u];i<G[u].size();i++)
{
node &now = e[G[u][i]];
if(now.cap>now.flow&&level[now.to]>level[u])
{
int d = dfs(now.to, v, min(f, now.cap - now.flow));
if(d>)
{
now.flow += d;
e[G[u][i] ^ ].flow -= d;
return d;
}
}
}
return ;
} int dinic()
{
int flow = ;
while()
{
bfs(s);
if (level[t] < ) return flow;
memset(iter, , sizeof(iter));
int f;
while ((f = dfs(s, t, inf)) > ) flow += f;
}
} int main()
{
int n;
cin >> n;
for (int i = ; i <= n; i++) cin >> a[i];
s = , t = * n + ;
int res = ;
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] + );
}
res = max(res, dp[i]);
}
printf("%d\n", res);
for (int i = ; i <= n; i++) add(i, i + n, );
for (int i = ; i <= n; i++) if (dp[i] == ) add(s, i, );
for (int i = ; i <= n; i++) if (dp[i] == res) add(i+n, t, );
for(int i=;i<=n;i++)
{
for(int j=;j<i;j++)
{
if (a[i] >= a[j] && dp[i] == dp[j] + ) add(j + n, i, );
}
}
int ans = dinic();
printf("%d\n", ans);
add(s, , inf);
add(, + n, inf);
if (dp[n] == res) add(n, t, inf),add(n, n + n, inf);
int ech = dinic();
printf("%d\n", ech+ans);
return ;
}
网络流 之 P2766 最长不下降子序列问题的更多相关文章
- P2766 最长不下降子序列问题 网络流重温
P2766 最长不下降子序列问题 这个题目还是比较简单的,第一问就是LIS 第二问和第三问都是网络流. 第二问要怎么用网络流写呢,首先,每一个只能用一次,所以要拆点. 其次,我们求的是长度为s的不下降 ...
- 【24题】P2766最长不下降子序列问题
网络流二十四题 网络流是个好东西,希望我也会. 网络流?\(orz\ zsy!!!!!\) P2766 最长不下降子序列问题 考虑我们是如何\(dp\)这个\(LIS\)的. 我们是倒着推,设置\(d ...
- [**P2766** 最长不下降子序列问题](https://www.luogu.org/problemnew/show/P2766)
P2766 最长不下降子序列问题 考虑我们是如何\(dp\)这个\(LIS\)的. 我们是倒着推,设置\(dp(i)\)代表以\(i\)为起点的\(LIS\)是多少.转移太显然了 \[ dp(i)=m ...
- P2766 最长不下降子序列问题 网络流
link:https://www.luogu.org/problemnew/show/P2766 题意 给定正整数序列x1,...,xn . (1)计算其最长不下降子序列的长度s. (2)计算从给定的 ...
- P2766 [网络流24题]最长不下降子序列问题
ha~ «问题描述: 给定正整数序列$x_1,...,x_n$ .$n<=500$ 求(1)计算其最长不下降子序列的长度$s$. (2)计算从给定的序列中最多可取出多少个长度为$s$的不下降子序 ...
- 【Luogu】P2766最长不下降子序列问题(暴力网络流)
题目链接 水题qwq,数据都那么水. 我要是出数据的人我就卡$n^3$建图. qwq. 然而这么水的题我!居!然!没!有!1!A!!还!提!交!了!五!遍!!! md从现在开始要锻炼1A率了 看我从今 ...
- P2766 最长不下降子序列问题 题解(网络流)
题目链接 最长不下降子序列问题 解题思路 分成三小问解决. 第一小问,求\(LIS\),因为\(n<=500\),直接\(O(N^2)\)暴力求解即可. 第二三小问,建立模型用网络流求解. 对于 ...
- 网络流24题 P2766 最长不下降子序列问题
题目描述 «问题描述: 给定正整数序列x1,...,xn . (1)计算其最长不下降子序列的长度s. (2)计算从给定的序列中最多可取出多少个长度为s的不下降子序列. (3)如果允许在取出的序列中多次 ...
- 洛谷 P2766 最长不下降子序列问【dp+最大流】
死于开小数组的WA?! 第一问n方dp瞎搞一下就成,f[i]记录以i结尾的最长不下降子序列.记答案为mx 第二问网络流,拆点限制流量,s向所有f[i]为1的点建(s,i,1),所有f[i]为mx(i+ ...
随机推荐
- RFID和QRCODE对比
1.技术介绍 1.1 RFID 射频识别,RFID(Radio Frequency Identification)技术,又称无线射频识别,是一种通信技术,可通过无线电讯号识别特定目标并读写相关数据,而 ...
- LeetCode算法题-Letter Case Permutation(Java实现)
这是悦乐书的第315次更新,第336篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第184题(顺位题号是784).给定一个字符串S,将每个字母单独转换为小写或大写以创建另 ...
- 如何在Microsoft Word里面插入图片作为背景/封面?
Stay hungry, Stay foolish. 如何在Word里面插入图片作为背景?其实很简单,开门见山,我们只需要这几步即可! 1.第一步,打开要插入图片的Word 2.第二步,插入图 ...
- 【Teradata】TD Unicode编码格式下varchar定义测试
如下测试表,每个字段字符编码格式均为Unicode. 1.varchar(1)可以存储1个汉字,也只能存储1个ASCII字符. --创建表nc_test,每个字段编码格式均设定为Unicode[使用S ...
- Java面向对象概述及三大特征(封装,继承和多态)
一.面向对象思想 Java是面向对象的高级语言,对于Java语言来说,万事万物皆对象! 它的基本思想是使用类,对象,继承,封装,消息等基本概念进行程序设计.面向对象程序的最小单元是类,类代表了客观世界 ...
- 音频处理EQ的基本概念
我们通常所说的人声,歌声以及乐声都是一个复合音,也就是由声音的基音和一系列的泛音所构成的.这些泛音都是基音频率的倍数,物理学中叫分音,电声学中叫谐波,音乐中则把它们称做泛音.可以说,泛音对音色的特性 ...
- .NET Core微服务之基于Ocelot实现API网关服务
Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.啥是API网关? API 网关一般放到微服务的最前端,并且要让API 网关变成由应用所发起的每个请求的入口.这样就可以明显的简化客户端 ...
- NavigationViewDemo【和DrawerLayout搭配使用实现侧滑导航视图界面】
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 主要记录NavigationView的使用,而一般情况下NavigationView是和DrawerLayout搭配使用的,还有To ...
- 通过数据分析告诉你北京Python开发的现状
相信各位同学多多少少在拉钩上投过简历,今天突然想了解一下北京Python开发的薪资水平.招聘要求.福利待遇以及公司地理位置.既然要分析那必然是现有数据样本.本文通过爬虫和数据分析为大家展示一下北京Py ...
- springboot~rabbitmq的队列初始化和绑定
配置文件,在rabbit中自动建立exchange,queue和绑定它们的关系 代码里初始化exchange 代码里初始化queue 代码里绑定exchange,queue和routekey 配置文件 ...