zoukankan      html  css  js  c++  java
  • [题解] PowerOJ 1756 最长k可重区间集问题 (最大费用最大流)

    - 传送门 -

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

    #  1756: 最长k可重区间集问题

    Time Limit: 1000 MS Memory Limit: 65536 KB
    Total Submit: 72 Accepted: 48 Page View: 467

    Description

    «编程任务: 对于给定的开区间集合I和正整数k,计算开区间集合I的最长k可重区间集的长度。

    Input

    由文件input.txt提供输入数据。文件的第1 行有2 个正整数n和k,分别表示开区间的 个数和开区间的可重迭数。接下来的n行,每行有2个整数,表示开区间的左右端点坐标。

    Output

    程序运行结束时,将计算出的最长k可重区间集的长度输出到文件output.txt中。

    4 2
    1 7
    6 8
    7 10
    9 13

    15

    Source

    线性规划与网络流24题

     

    - 思路 -

     把一个区间分成两个点什么的我是真的没想到了.
     所以就直接把离散化后的点排好, 最后一个点连向汇点的容量为 k.
     区间就直接找到表示其左右端点的点连起来, 容量为 1, 费用为区间长.
     求最大费用最大流.
     
     细节见代码.
     

    - 代码 -

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
     
    const int N = 1100;
    const int M = 5000;
    const int inf = 0x3f3f3f3f;
     
    struct node {
        int x, id;
        bool operator < (const node &tmp) const {
            return x < tmp.x;
        }
    }LS[N];
     
    int A[N], S[N];
    int NXT[M], TO[M], V[M], CT[M];
    int HD[N], DIS[N], VIS[N], PRE[N];
    int ss, tt, n, k, sz, tot;
    queue<int> q;
     
    void add(int x, int y, int z, int c) {
        TO[sz] = y; V[sz] = z; CT[sz] = c;
        NXT[sz] = HD[x]; HD[x] = sz++;
        TO[sz] = x; V[sz] = 0; CT[sz] = -c;
        NXT[sz] = HD[y]; HD[y] = sz++;  
    }
     
    bool spfa() {
        memset(DIS, 0xc0, sizeof (DIS));
        DIS[ss] = 0;
        q.push(ss);
        while (!q.empty()) {
            int u = q.front();
            VIS[u] = 0;
            q.pop();
            for (int i = HD[u]; i != -1; i = NXT[i]) {
                int v = TO[i];
                if (V[i] && DIS[v] < DIS[u] + CT[i]) {
                    DIS[v] = DIS[u] + CT[i];
                    PRE[v] = i;
                    if (!VIS[v]) {
                        VIS[v] = 1;
                        q.push(v);
                    }
                }
            }
        }
        return DIS[tt] > 0;
    }
     
    int macmf() {
        int cost = 0;
        while (spfa()) {
            int tmp = inf;
            for (int i = tt; i != ss; i = TO[PRE[i]^1])
                if (tmp > V[PRE[i]])
                    tmp = V[PRE[i]];
            for (int i = tt; i != ss; i = TO[PRE[i]^1]) {
                V[PRE[i]] -= tmp;
                V[PRE[i]^1] += tmp;
            }
            cost += tmp * DIS[tt];
        }
        return cost;
    }
     
    int main() {
        memset(HD, -1, sizeof (HD));
        scanf("%d%d", &n, &k);
        for (int i = 1, x, y; i <= n; ++i) {
            scanf("%d%d", &x, &y);
            LS[i].x = x; LS[i].id = i;
            LS[i + n].x = y; LS[i + n].id = i + n;
            S[i] = y - x;
        }
        sort(LS + 1, LS + n + n + 1);
        for (int i = 1; i <= n * 2; ++i) {
            A[LS[i].id] = A[LS[i - 1].id];
            if (LS[i].x != LS[i - 1].x)
                A[LS[i].id] = ++tot;
        }
        ss = 0, tt = ++tot;
        add(ss, 1, k, 0);
        add(tot, tt, k, 0);
        for (int i = 1; i < tot; ++i)
            add(i, i + 1, inf, 0);
        for (int i = 1; i <= n; ++i)
            add(A[i], A[i + n], 1, S[i]);
        printf("%d
    ", macmf());
        return 0;
    }
    
  • 相关阅读:
    POJ 2018 二分
    873. Length of Longest Fibonacci Subsequence
    847. Shortest Path Visiting All Nodes
    838. Push Dominoes
    813. Largest Sum of Averages
    801. Minimum Swaps To Make Sequences Increasing
    790. Domino and Tromino Tiling
    764. Largest Plus Sign
    Weekly Contest 128
    746. Min Cost Climbing Stairs
  • 原文地址:https://www.cnblogs.com/Anding-16/p/7426351.html
Copyright © 2011-2022 走看看