Los longest valley P2766 does not drop subsequence problem

\ (\ quad \) Once you know this question is a network stream, thinking it is a miss.
\ (\ Quad \) first with \ (O (^ n-2) \) DP obtains \ (DP \) and \ (S \) . Here \ (dp_i \) represents the \ ([1, i] \ ) last element in the range of \ (I \) does not decrease the length of the longest sequence.

for(int i = 1; i <= n; ++i)
    for(int j = 0; j < i; ++j){
        if(x[j] <= x[i])
            dp[i] = max(dp[i], dp[j] + 1);
        s = max(s, dp[i]);
    }

\ (\ Quad \) \ (\ mathrm the I {.} \)
\ (\ qquad \) directly outputs \ (S \) can.
\ (\ Quad \) \ (\ mathrm {II.} \)
\ (\ qquad \) \ (\ FORALL I, J \) satisfies \ (i> j \) and \ (x_i \ GEQ x_j \) , even one from \ (r_j \) to \ (L_i \) , capacity \ (1 \) directed edge; \ (\ FORALL I \) satisfies \ (dp_i = 1 \) , even one from source to \ ( L_i \) , capacity \ (1 \) directed edge; \ (\ FORALL I \) satisfies \ (dp_i = S \) , even one from \ (r_i \) to sink, capacity \ (1 \ ) directed edge, \ (\ FORALL I \) , even from a \ (L_i \) to\ (r_i \) , capacity \ (1 \) directed edge. This figure is the maximum flow of the answer.
\ (\ Quad \) \ (\ mathrm {III.} \)
\ (\ qquad \) begins as all elements to this question can be repeatedly used, the tone for a long time - directly connected \ ((s, l_1 ) \) , \ ((L_1, R_1) \) , \ ((L_n, R_n) \) , \ ((R_n, T) \) capacity \ (+ \ infty \) directed to edge.

#include <cstdio>
#include <cstring>
#include <queue>

inline int max(const int& a, const int& b){
    return a > b ? a : b;
}

inline int min(const int& a, const int& b){
    return a < b ? a : b;
}

const int MAXN = 5e2 + 19, INF = 0x3f3f3f3f;

struct Edge{
    int to, next, c;
}edge[MAXN * MAXN << 1];

int cnt = -1, head[MAXN << 1];

inline void add(int from, int to, int c){
    edge[++cnt].to = to;
    edge[cnt].c = c;
    edge[cnt].next = head[from];
    head[from] = cnt;
}

int n, x[MAXN], s;
int dep[MAXN << 1];

int bfs(void){
    std::memset(dep, 0, sizeof(dep)); dep[0] = 1;
    std::queue<int>q; q.push(0);
    while(!q.empty()){
        int node = q.front();
        for(int i = head[node]; i != -1; i = edge[i].next)
            if(!dep[edge[i].to] && edge[i].c)
                dep[edge[i].to] = dep[node] + 1, q.push(edge[i].to);
        q.pop();
    }
    return dep[n + n + 1];
}

int dfs(int node, int flow){
    if(node == n + n + 1 || !flow)
        return flow;
    int stream = 0, f;
    for(int i = head[node]; i != -1; i = edge[i].next)
        if(dep[edge[i].to] == dep[node] + 1 && (f = dfs(edge[i].to, min(flow, edge[i].c)))){
            flow -= f, stream += f;
            edge[i].c -= f, edge[i ^ 1].c += f;
            if(!flow)
                break;
        }
    return stream;
}

int dinic(void){
    int flow = 0;
    while(bfs())
        flow += dfs(0, INF);
    return flow;
}

int dp[MAXN], ans;

int main(){
    std::scanf("%d", &n);
    for(int i = 1; i <= n; ++i)
        std::scanf("%d", x + i);
    for(int i = 1; i <= n; ++i)
        for(int j = 0; j < i; ++j){
            if(x[j] <= x[i])
                dp[i] = max(dp[i], dp[j] + 1);
            s = max(s, dp[i]);
        }
    std::printf("%d\n", s);
    std::memset(head, -1, sizeof(head));
    for(int i = 1; i <= n; ++i)
        add(i, i + n, 1), add(i + n, i, 0);
    for(int i = 1; i <= n; ++i){
        if(dp[i] == 1)
            add(0, i, 1), add(i, 0, 0);     
        for(int j = 1; j < i; ++j)
            if(dp[i] == dp[j] + 1 && x[i] >= x[j])
                add(j + n, i, 1), add(i, j + n, 0);
        if(dp[i] == s)
            add(i + n, n + n + 1, 1), add(n + n + 1, i + n, 0);
    }
    std::printf("%d\n", ans = dinic());
    add(0, 1, INF), add(1, 0, 0), add(1, 1 + n, INF), add(1 + n, 1, 0);
    if(dp[n] == s)
        add(n, n + n, INF), add(n + n, n, 0), add(n + n, n + n + 1, INF), add(n + n + 1, n + n, 0);
    std::printf("%d\n", ans + dinic());
    return 0;
}

\ (\ quad \) there are a lot of weird data on this question Luo Gu, good Fana.

Guess you like

Origin www.cnblogs.com/natsuka/p/12300474.html