嘘~ 正在从服务器偷取页面 . . .

洛谷P2766 最长不下降子序列问题 题解


洛谷P2766 最长不下降子序列问题 题解

题目链接:P2766 最长不下降子序列问题

题意

给定正整数序列 \(x_1 \ldots, x_n\)

  1. 计算其最长不下降子序列的长度 \(s\)
  2. 如果每个元素只允许使用一次,计算从给定的序列中最多可取出多少个长度为 \(s\) 的不下降子序列。
  3. 如果允许在取出的序列中多次使用 \(x_1\)\(x_n\)(其他元素仍然只允许使用一次),则从给定序列中最多可取出多少个不同的长度为 \(s\) 的不下降子序列。

\(a_1, a_2, \ldots, a_s\) 为构造 \(S\) 时所使用的下标,\(b_1, b_2, \ldots, b_s\) 为构造 \(T\) 时所使用的下标。且 \(\forall i \in [1,s-1]\),都有 \(a_i \lt a_{i+1}\)\(b_i \lt b_{i+1}\)。则 \(S\)\(T\) 不同,当且仅当 \(\exists i \in [1,s]\),使得 \(a_i \neq b_i\)

输入格式

第一行有一个正整数 \(n\),表示给定序列的长度。接下来的一行有 \(n\) 个正整数\(x_1, ..., x_n\)

输出格式

  • \(1\) 行是最长不下降子序列的长度 \(s\)
  • \(2\) 行是可取出的长度为 \(s\) 的不下降子序列个数。
  • \(3\) 行是允许在取出的序列中多次使用 \(x_1\)\(x_n\) 时可取出的长度为 \(s\)不同的不下降子序列个数。

数据范围

\(1 \le n\le 500\)

第一问就是萌萌dp,我觉得 cxy 都能做

考虑第二问怎么做。

每个点只能用一次,考虑拆点,把 \(i\) 拆成 \(i_{x},i_{y}\)\(i_x\)\(i_y\) 连一条流量为 \(1\) 的边。

因为要是最长不下降子序列,所以选点 \(j\) 的下一个点 \(i\) 时,要严格满足 \(f_j = f_i - 1\)

因此我们将这样的 \(j_y\)\(i_x\) 连边,流量为 \(1\) (因为对于这样的 \((j,i)\) 只支持一次匹配)

然后 \(s\)\(f_i=1\)\(i_x\) 连边,流量为 \(1\)\(f_i=s\)\(i_y\)\(t\) 连边,流量为 \(1\)

跑一遍最大流就是答案。

第三问其实就是稍微改了一改:

  • \(j=1\) 时,\((j,i)\) 可以匹配多次,对应边 \((1,i)\)
  • \(j=n \land f_n = s\) 时,\(n \to t\) 可以有多条匹配,对应边 \((n,t)\)
  • 还有 \(j_x \to j_y~(j=1\lor(j=n\land f_n=s))\) 也可以匹配多条。

我们直接在残量网络上建新边,流量为 \(+\infty\) ,再跑一遍最大流即可,注意这是在第二问基础上的增量。

注意这里有一个很特殊的情况,需要特判,即输入 1 1 的时候,第三问我们会建出来这样的图

这个时候跑出来的最大流会变成 \(+\infty\) ,所以需要特判一下,答案是 \(1\)

理论时间复杂度 \(\mathcal{o}(n^4)\) ,因为边数其实远小于 \(\mathcal{O}(n^2)\)

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)(505 * 2 + 15))
#define M ((int)(N * N * 2 + 3 * N * 2))

int n,m,s,t,tot,pos=1,a[N],dp[N],dep[N],now[N],head[N];
// A : 1 ~ n, A' : n+1 ~ n+n
struct Edge { int u,v,w,next; } e[M];
void addEdge(int u,int v,int w)
{ e[++pos] = {u,v,w,head[u]}; head[u] = pos; }
void add(int u,int v,int w) { addEdge(u,v,w); addEdge(v,u,0); }
queue<int> q;
bool bfs()
{
    for(int i=1; i<=tot; i++) dep[i] = INF;
    dep[s] = 1; q.push(s); now[s] = head[s];
    while(!q.empty())
    {
        int u = q.front(); q.pop();
        for(int i=head[u]; i; i=e[i].next)
        {
            int v = e[i].v;
            if(e[i].w > 0 && dep[v] == INF)
            {
                dep[v] = dep[u] + 1;
                now[v] = head[v]; q.push(v);
            }
        }
    }
    return dep[t] != INF;
}
int dfs(int u,int in)
{
    if(u == t) return in;
    int out = 0;
    for(int i=now[u]; i && in; i = e[i].next)
    {
        int v = e[i].v; now[u] = i;
        if(e[i].w > 0 && dep[v] == dep[u] + 1)
        {
            int res = dfs(v, min(in, e[i].w));
            e[i].w -= res; e[i ^ 1].w += res;
            in -= res; out += res;
        }
    }
    if(!out) dep[u] = INF;
    return out;
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    cin >> n; s = n + n + 1; tot = t = s + 1;
    if(n == 1) { return cout << "1\n1\n1\n", 0; }
    for(int i=1; i<=n; i++) cin >> a[i];
    for(int i=1; i<=n && (dp[i] = 1); i++)
    {
        for(int j=1; j<i; j++)
            if(a[j] <= a[i]) up(dp[i], dp[j] + 1);
        up(m, dp[i]);
    }
    cout << m << '\n';
    for(int i=1; i<=n; i++) add(i, n + i, 1); // A -> A'
    for(int i=1; i<=n; i++) if(dp[i] == 1) add(s, i, 1); // s -> A
    for(int i=1; i<=n; i++) if(dp[i] == m) add(n + i, t, 1); // A' -> t
    for(int i=1; i<=n; i++) for(int j=1; j<i; j++)
        if(a[j] <= a[i] && dp[i] - 1 == dp[j]) add(n + j, i, 1); // x -> y
    int res = 0;
    while(bfs()) res += dfs(s,INF);
    cout << res << '\n';
    add(1, n + 1, INF); add(s, 1, INF);
    if(dp[n] == m) { add(n + n, t, INF); add(n, n + n, INF); }
    while(bfs()) res += dfs(s,INF);
    cout << res << '\n';
    return 0;
}

参考文献

[1] https://www.luogu.com.cn/blog/PopulusEuphratica/luogup2766-zui-zhang-fou-xia-xiang-zi-xu-lie-wen-ti


文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录