zoukankan      html  css  js  c++  java
  • [题解] PowerOJ 1741 最长递增子序列问题 (最大流)

    - 传送门 -

     https://www.oj.swust.edu.cn/problem/show/1741

    #  1741: 最长递增子序列问题

    Time Limit: 1000 MS Memory Limit: 65536 KB
    Total Submit: 379 Accepted: 67 Page View: 1046

    Description

    给定正整数序列x1 ,... , xn 。 (1)计算其最长递增子序列的长度s。(严格递增) (2)计算从给定的序列中最多可取出多少个长度为s的递增子序列。 (3)如果允许在取出的序列中多次使用x1和xn,则从给定序列中最多可取出多少个长 度为s的递增子序列。 编程任务: 设计有效算法完成(1)(2)(3)提出的计算任务。

    Input

    由文件input.txt提供输入数据。文件第1 行有1个正整数n(n<400),表示给定序列的长度。接 下来的1 行有n个正整数 x1 , ... , xn。

    Output

    程序运行结束时,将任务(1)(2)(3)的解答输出到文件output.txt中。第1 行是最长 递增子序列的长度s。第2行是可取出的长度为s 的递增子序列个数。第3行是允许在取出 的序列中多次使用x1和xn时可取出的长度为s 的递增子序列个数。

    Source

    线性规划与网络流24题

     

    - 思路 -

     第一问dp.
     (设(A_x)表示原数列中第 (x) 个数, (F[x]) 表示以第 (x) 个数结束的最长不降子序列的长度, (s), (t) 表示起点终点)
     第二问最大流, 对于(A_i<A_j)(F_i+1==F_j)(i<j) 的点对建 (i o j), 对于(F _x=1)的点建(s o x), 对于$F_x = ans1 $ (第一问答案)的点建 (x o t), 求最大流.
     第三问将(s o 1)(n o t)的容量设为一个极大值, 再求最大流.
     
     细节见代码.
     

    - 代码 -

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
     
    const int N = 400 + 5;
    const int M = 2e5 + 5;
    const int inf = 0x3f3f3f3f;
     
    int F[N], A[N];
    int HD[N], CUR[N];
    int NXT[M], FRM[M], TO[M], V[M];
    int DIS[N];
    int n, m, ans, sz, cnt, ss, tt;
    queue<int> q;
     
    void add(int x, int y) {
        TO[sz] = y; FRM[sz] = x; V[sz] = 1;
        NXT[sz] = HD[x]; HD[x] = sz++;
        TO[sz] = x; FRM[sz] = y; V[sz] = 0;
        NXT[sz] = HD[y]; HD[y] = sz++;
    }
     
    bool bfs() {
        memset(DIS, -1, sizeof (DIS));
        DIS[ss] = 0;
        q.push(ss);
        while (!q.empty()) {
            int u = q.front();
            q.pop();
            for (int i = HD[u]; i != -1; i = NXT[i]) {
                int v = TO[i];
                if (DIS[v] < 0 && V[i]) {
                    q.push(v);
                    DIS[v] = DIS[u] + 1;
                }
            }
        }
        return DIS[tt] > 0;
    }
     
     
    int dfs(int x,int a) {
        if (x == tt) return a;
        int flow = 0, f;
        for (int& i = CUR[x]; i != -1; i = NXT[i]) {
            if (V[i] && DIS[TO[i]] == DIS[x] + 1)
                if (f = dfs(TO[i], min(a, V[i]))) {
                    V[i] -= f;
                    V[i^1] += f;
                    flow += f;
                    a -= f;
                    if (a == 0) break;
                }
        }
        return flow;
    }
     
    int dinic() {
        int flow = 0;
        while (bfs()) {
            memcpy(CUR, HD, sizeof (HD));
            flow += dfs(ss, inf);
        }
        return flow;
    }
     
    int main() {
        memset(HD, -1, sizeof (HD));
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) {
            scanf("%d", &A[i]);
            F[i] = 1;
            for (int j = 1; j < i; ++j) {
                if (A[j] < A[i])
                    F[i] = max(F[i], F[j] + 1);
            }
            ans = max(ans, F[i]);
        }
        printf("%d
    ", ans);
        ss = 0, tt = n + 1;
        for (int i = 1; i <= n; ++i) {
            if (F[i] == 1) add(ss, i);
            if (F[i] == ans) add(i, tt);
            for (int j = 1; j < i; ++j) {
                    if (A[j] < A[i] && F[j] + 1 == F[i])
                        add(j, i);
                }
        }
        printf("%d
    ", dinic());
        for (int i = 0; i < sz; ++i) {
            if (TO[i] == 1) V[i] = inf;
            else if (FRM[i] == n) V[i] = inf;
            else V[i] = (i % 2) ^ 1; //更改以及初始化边容量
        }
        printf("%d
    ", dinic());
        return 0;
    }
    
  • 相关阅读:
    【JVM】内存与垃圾回收
    【缓存】缓存与分布式锁
    【Redis】入门与基础总结
    【Elasticsearch7.x】Elasticsearch 入门
    iOS开发ReactiveCocoa学习笔记(六)
    iOS开发ReactiveCocoa学习笔记(五)
    iOS开发ReactiveCocoa学习笔记(四)
    iOS开发ReactiveCocoa学习笔记(三)
    iOS开发ReactiveCocoa学习笔记(二)
    iOS开发ReactiveCocoa学习笔记(一)
  • 原文地址:https://www.cnblogs.com/Anding-16/p/7413352.html
Copyright © 2011-2022 走看看