# 6005. "24 network flow problem," the longest increasing subsequence

# 6005
title meaning
given sequence of positive integers x1, ..., xn.
(1) calculate the length s longest increasing sequence.
(2) increasing subsequence of s calculated from a given maximum number of sequence lengths can be removed. (Each number can only take one)
(3) if permitted x1 and xn taken in sequence repeatedly, from the given sequence length of the maximum number of removed increments of the sequence s.
Thinking
first question: n ^ dp 2 buttoned, the processing array dp, dp [i] is a number represented by the subscript i is the length of the longest sequence is not reduced end is.
The second question: each number can only be taken once, consider using dinic to write, that is, the number of traffic. FIG mainly in the construction, there are two built FIG limitation, one each only take a few, there is the desired length is s. Condition may only take a split point with solution, to a point i split into two points i, i + n, then i and i + n is connected between one side of the capacity of 1, then if the point i from the point j associated, then it is connected to a i + n, so as to ensure each point only once, after the capacity limit is 1; next is the source and a dp [i] is connected to the point 1, DP [ i] s is the sink point is connected, satisfy the relationship a [i]> = a [ j] && dp [i] == dp [j] of point i +1, j, n are connected to the j + i, and finally seeking maximum flow.
Third question: x1, xn can be used multiple times, then add the source to the flow of INF 1 side, 1 and 1 + n flow INF side, n and n + n flow INF side, if dp [n] == s, then n + n must be added to the meeting point of the edge INF. Finally, seeking maximum flow.

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e4 + 7;
typedef long long ll;
struct Edge {
    int from, to, cap, flow;
    Edge(int u, int v, int c, int f):from(u), to(v), cap(c), flow(f) {}
};
struct Dinic {
    int n, m, s, t;
    vector<Edge> edges;
    vector<int> G[maxn];
    int d[maxn], cur[maxn];
    bool vis[maxn];

    void init(int n) {
        for (int i = 0; i < n; i++) G[i].clear();
        edges.clear();
    }

    void add(int from, int to,int cap) {
        edges.push_back(Edge(from, to, cap, 0));
        edges.push_back(Edge(to, from, 0, 0));
        m = edges.size();
        G[from].push_back(m - 2);
        G[to].push_back(m - 1);
    }

    bool BFS() {
        memset(vis, 0, sizeof(vis));
        queue<int> que;
        que.push(s);
        d[s] = 0;
        vis[s] = 1;
        while (!que.empty()) {
            int x = que.front();
            que.pop();
            for (int i = 0; i < G[x].size(); i++) {
                Edge& e = edges[G[x][i]];
                if(!vis[e.to] && e.cap > e.flow) {
                    vis[e.to] = 1;
                    d[e.to] = d[x] + 1;
                    que.push(e.to);
                }
            }
        }
        return vis[t];
    }

    int DFS(int x, int a) {
        if(x == t || a == 0) return a;
        int flow = 0, f;
        for (int &i = cur[x]; i < G[x].size(); i++) {
            Edge& e = edges[G[x][i]];
            if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0) {
                e.flow += f;
                edges[G[x][i] ^ 1].flow -= f;
                flow += f;
                a -= f;
                if(a == 0) break;
            }
        }
        return flow;
    }

    int Maxflow(int s, int t) {
        this->s = s;
        this->t = t;
        int flow = 0;
        while (BFS()) {
            memset(cur, 0, sizeof(cur));
            flow += DFS(s, INF);
        }
        return flow;
    }
};
int a[maxn], dp[maxn];
int main()
{
    int n, m, s, t;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]), dp[i] = 1;
    int maxx = 1;
    for (int i = 2; i <= n; i++) {
        for (int j = 1; j < i; j++)
            if(a[i] >= a[j]) dp[i] = max(dp[i], dp[j] + 1);
        maxx = max(maxx, dp[i]);
    }
    if(n == 1) {
        printf("1\n1\n1\n");
        return 0;
    }
    printf("%d\n", maxx);
    Dinic solve;
    s = 0, t = n * 2 + 1;
    for (int i = 1; i <= n; i++) {
        solve.add(i, i + n, 1);
        if(dp[i] == 1) solve.add(s, i, 1);
        if(dp[i] == maxx) solve.add(i + n, t, 1);
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j < i; j++) {
            if(dp[j] + 1 == dp[i] && a[j] <= a[i]) solve.add(j + n, i, 1);//***
        }
    }
    int ans = solve.Maxflow(s, t);
    printf("%d\n", ans);
    solve.add(s, 1, INF);
    solve.add(1, 1 + n, INF);
    solve.add(n, n + n, INF);
    if(dp[n] == maxx) solve.add(n + n, t, INF);
    ans += solve.Maxflow(s, t);//注意是加上,因为是在原图的基础上加了边再找增广路。
    printf("%d\n", ans);
}

Published 26 original articles · won praise 2 · Views 400

Guess you like

Origin blog.csdn.net/D_Bamboo_/article/details/104051866