码迷,mamicode.com
首页 > 其他好文 > 详细

「网络流24题」最长不下降子序列问题

时间:2018-08-05 10:28:36      阅读:145      评论:0      收藏:0      [点我收藏+]

标签:解决问题   拆点   容量   get   思路分析   细节   blank   soft   暴力   

传送门:>Here<

题意:

给定正整数序列$x_1,...,x_n$

(1)计算其最长不下降子序列的长度s。

(2)计算从给定的序列中最多可取出多少个长度为s的不下降子序列。

(3)如果允许在取出的序列中多次使用$x_1$和$x_n$,则从给定序列中最多可取出多少个长度为$s$的不下降子序列。

思路分析

题意首先就很坑:注意第二问中的取出二字,意味着一个数字最多只能存在于一个LIS中。所以才会有第三问的假设

第一问很简单,直接暴力$O(n^2)$就好了

后面的两问需要借助于网络流。很容易想到:令S到T的任意一条路径表示一个LIS,并且设边的容量为1。这样的话最大流也就是能取出的LIS数量(和二分图匹配原理一样,一个点不会被用两次)

因此我们还是需要像二分图匹配一样拆点,每个点拆为两个。然后令$f[i]=1$的点连源点,$f[i]=maxs$的点连汇点。然后我们最初的想法是f值连续递增的并且能组成不下降子序列的两数之间连边即可。但这里情况也许不同了,想象一个类似$5,4,3,2,1$这样完全下降的序列,这样的话两部分的点之间不能连任何边,最大流跑出来是0。然而由于LIS长度为1,很明显有5种取法!

因此我们考虑,被拆的两个点自己连到自己,并且递增的边反过来连,就能解决问题。这样表达不清晰,下面详细阐述如何连边:

首先原序列做LIS,其中$f[i]$表示以$a[i]$为结尾的LIS的最大长度。对序列的每一个数进行拆点,也就是分为$X_i, Y_i$。我们要让S到T的每一条路径都是一个LIS,因此若$f[i]=1$,则$X_i$的点连接源点,$f[i]=maxs$则$Y_i$连接汇点。其中对于每一个数字,连接有向边$(X_i, Y_i)$。并且在做LIS的过程中,若发现一对数字满足$a[j]<=a[i] 且 f[j]+1=f[i]$,则连有向边$(Y_j, X_i)$。最后做最大流即可

Code

细节题

「网络流24题」最长不下降子序列问题

标签:解决问题   拆点   容量   get   思路分析   细节   blank   soft   暴力   

原文地址:https://www.cnblogs.com/qixingzhi/p/9424520.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!