网络流样例不过求条

P2766 最长不下降子序列问题

xudongyi1 @ 2024-08-13 11:03:19

rt,救一下吧。

#include <bits/stdc++.h>
#define int long long
using namespace std;
inline int read()
{
    int s = 0, w = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-') w = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        s = (s << 3) + (s << 1) + (ch ^ 48);
        ch = getchar();
    }
    return s * w;
}
const int N = 1e5 + 10;
int dp[N], n, a[N];
int s, t = 10000;
int head[N], ne[N], to[N], w[N], id = 1;
void add(int x, int y, int z)
{
    to[++id] = y, ne[id] = head[x], w[id] = z, head[x] = id;
    to[++id] = x, ne[id] = head[y], w[id] = 0, head[y] = id;
}
int now[N];
int dis[N], q[N], l, r;
void bfs(int s)
{
    memset(dis, -1, sizeof dis);
    dis[q[l = r = 1] = s] = 0;
    while(l <= r)
    {
        int u = q[l++];
        for(int i = head[u]; i; i = ne[i])
        {
            int v = to[i];
            if(w[i] && !~dis[v])
            {
                dis[v] = dis[u] + 1;
                q[++r] = v;
            }
        }
    }
    return ;
}
int dfs(int u, int f)
{
    if(u == t) return f;
    int res = f;
    for(int &i = now[u]; i; i = ne[i])
    {
        int v = to[i];
        if(w[i] && dis[v] == dis[u] + 1)
        {
            int t = dfs(v, min(res, w[i]));
            if(t)
            {
                w[i] -= t;
                w[i ^ 1] += t;
                res -= t;
                if(!res) break;
            }
            else dis[v] = 0;
        }
    }
    return f - res;
}
int dinic()
{
    int ans = 0, f;
    while(1)
    {
        for(int i = 0; i <= 10000; i++) now[i] = head[i];
        bfs(s);
        f = dfs(s, 1e18);
        if(!f) return ans;
        ans += f;
    }
    return -1;
}
signed main()
{
    n = read();
    for(int i = 1; i <= n; i++) a[i] = read();
    s = 0, t = n + n + 1;
    int mx = 0;
    for(int i = 1; i <= n; i++)
    {
        dp[i] = 1;
        for(int j = 1; j < i; j++)
        {
            if(a[j] <= a[i]) dp[i] = max(dp[i], dp[j] + 1);
        }
        mx = max(mx, dp[i]);
        /*
        question 1
        */
    }
    printf("%lld\n", mx);
    // 拆成两个点
    for(int i = 1; i <= n; i++) add(i, i + n, 1);
    for(int i = 1; i <= n; i++) if(dp[i] == 1) add(s, i, 1);
    for(int i = 1; i <= n; i++) if(dp[i] == mx) add(i + n, t, 1);
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j < i; j++)
        {
            if(a[j] <= a[i] && dp[i] == dp[j] + 1) add(j + n, i, 1);
        }
    }
    printf("%lld\n", dinic());
    add(1, n + 1, 1e18);
    add(s, 1, 1e18);
    if(dp[n] == mx) add(n, n + n, 1e18), add(n + n, t, 1e18);
    printf("%lld\n", dinic());
    return 0;
}

|