码迷,mamicode.com
首页 > 其他好文 > 详细

【网络流24题】 5. 最长不下降子序列问题

时间:2020-09-17 13:40:27      阅读:27      评论:0      收藏:0      [点我收藏+]

标签:+=   tps   pac   ||   inline   return   lin   code   完全   

这道题有亿点难QAQ,虽然蒟蒻我已经做完了,不过我想完全理解本题以后再写题解,所以先占个坑QwQ

先贴一下代码:

发这么晚当然是因为我看了一天番QwQ

/**
 * luogu P2766 https://www.luogu.com.cn/problem/P2766
 * Dinic
 **/

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

const int maxn = 5005;
const int maxm = 550000;
const int s = 0;
const int t = maxn - 1;
const int INF = 0x3f3f3f3f;

using namespace std;

struct Edge {
    int to, val, nxt;
}e[maxm];

int numedge, head[maxn], n, num[maxn], f[maxn], depth[maxn], a[maxn], ans, res;

inline void AddEdge(int from, int to, int val) {
    e[numedge].to = to;
    e[numedge].val = val;
    e[numedge].nxt = head[from];
    head[from] = numedge;
    numedge++;
}

inline bool bfs() {
    memset(depth, 0, sizeof(depth));
    depth[s] = 1;
    queue<int> q;
    q.push(s);
    
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (int i = head[u]; ~i; i = e[i].nxt) {
            int to = e[i].to;
            if (!depth[to] && e[i].val > 0) {
                depth[to] = depth[u] + 1;
                q.push(to);
            }
        }
    }
    return depth[t] != 0;
}

int dfs(int u, int flow) {
    if (u == t || flow == 0) return flow;
    int res = 0;
    for (int i = head[u]; ~i; i = e[i].nxt) {
        int to = e[i].to;
        if (depth[to] == depth[u] + 1 && e[i].val > 0) {
            int di = dfs(to, min(flow, e[i].val));
            if (di > 0) {
                e[i].val -= di;
                e[i ^ 1].val += di;
                flow -= di;
                res += di;
            }
        }
    }
    if (!res) depth[u] = 0;
    return res;
}

void Dinic() {
    while (bfs()) {
        res += dfs(s, INF);
    }
}

int main() {
    memset(head, -1, sizeof(head));
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", a + i);
        f[i] = 1;
    }
    
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j < i; j++) {
            if (a[i] >= a[j]) {
                f[i] = max(f[i], f[j] + 1);
            }
        }
        ans = max(ans, f[i]);
    }
    printf("%d\n", ans);

    for (int i = 1; i <= n; i++) {
        AddEdge(i, i + n, 1);
        AddEdge(i + n, i, 0);
        if (f[i] == 1) {
            AddEdge(s, i, 1);
            AddEdge(i, s, 0);
        }
        if (f[i] == ans) {
            AddEdge(i + n, t, 1);
            AddEdge(t, i + n, 0);
        }
    }

    for (int i = 2; i <= n; i++) {
        for (int j = 1; j < i; j++) {
            if (a[j] <= a[i] && f[i] == f[j] + 1) {
                AddEdge(j + n, i, 1);
                AddEdge(i, j + n, 0);
            }
        }
    }
    Dinic();
    printf("%d\n", res);
    
    AddEdge(s, 1, INF);
    AddEdge(1, s, 0);
    AddEdge(1, 1 + n, INF);
    AddEdge(1 + n, 1, 0);
    if (f[n] == ans && n > 1) {
        AddEdge(n, n + n, INF);
        AddEdge(n + n, n, 0);
        AddEdge(n + n, t, INF);
        AddEdge(t, n + n, 0);
    }
    Dinic();
    printf("%d\n", res);
    return 0;
}

【网络流24题】 5. 最长不下降子序列问题

标签:+=   tps   pac   ||   inline   return   lin   code   完全   

原文地址:https://www.cnblogs.com/icysky/p/13616468.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!