ロス最長の谷P2766は、サブシーケンスの問題をドロップしません。

\(\クワッド\)あなたが知ったら、この質問は、それがミスで考えて、ネットワークストリームです。
\(\クワッド\)第一と\(O(^ N-2)\) DP取得\(DP \)\(S \) ここで\(dp_i \)を表し\([1、i]は\ ) の範囲内の最後の要素\(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]);
    }

\(\クワッド\) \(\ \ Iを{。} mathrm)
\(\ qquad \)を直接出力(S \)\できます。
\(\クワッド\) \(\ mathrm {II。} \)
\(\ qquad \) \(\ FORALL I、J \)を満足\(I> J \)\(X_I \ GEQ X - jが\) も1 \(r_j \)\(L_iを\) 容量\(1 \) ;有向エッジ(\ \ FORALL I \)を満足\(dp_i = 1 \)もつのソースからの、(\ L_iを\) 容量\(1 \)有向枝; \(\ FORALL I \)を満足\(dp_i = S \) 一つでもから\(R_iを\)シンクには、容量\(1 \ )、有向エッジ(\ \ FORALL I \) 偶数から\(L_iを\)\(R_iを\) 容量\(1 \)有向枝。この図は、解答の最大流量です。
\(\クワッド\) \(\ mathrm {III。} \)
\(\ qquad \)この質問へのすべての要素として始まり、繰り返し使用することができ、長時間のトーン-直接接続された\((S、L_1 )\)、\ ((L_1、 R_1)\)、\ ((L_n、たR_n)\)、\ ((たR_n、T)\)容量\(+ \ inftyの\)エッジに向け。

#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;
}

\(\クワッド\)この質問羅区、良いファナの奇妙なデータがたくさんあります。

おすすめ

転載: www.cnblogs.com/natsuka/p/12300474.html