zoukankan      html  css  js  c++  java
  • P3358 最长k可重区间集问题

    P3358 最长k可重区间集问题

    题目链接

    输入最多500个点对,即离散化后最多有1000个坐标。

    对离散化后的坐标建图。

    方法一: 将坐标从小到大连边,一个点与它后面相邻的点建一条边(流量为inf,花费为0),点对的左端点与右端点建一条边(流量为1,花费为(-区间长度)),s与第一个点建一条边(流量为k,花费为0),最后一个点与t建一条边(流量为k,花费为0)
    方法二: s与s'之间建一条边(流量为k,花费为0),s'与各区间左端点之间建一条边(流量为1,花费为0),区间左端点向本区间的右端点建一条边(流量为1,花费为(-区间长度)),区间右端点与比它大的区间左端点建边(流量为1,花费为0),各区间右端点与t建一条边(流量为1,花费为0)

    方法一代码:

    #include <bits/stdc++.h>
    
    using namespace std;
    #define ll long long
    const int maxn = 10010;
    const int maxm = 100010;
    const int inf = 0x3f3f3f3f;
    struct edge {
        int to, next, cap, flow, cost;
    } e[maxm];
    int head[maxn], tot;
    int pre[maxn], dis[maxn];
    bool vis[maxn];
    int N;
    
    void init(int n) {
        N = n;
        tot = 1;
        memset(head, 0, sizeof(head));
    }
    
    void addedge(int u, int v, int cap, int cost) {
        e[++tot].to = v, e[tot].next = head[u], e[tot].cap = cap, e[tot].cost = cost, e[tot].flow = 0, head[u] = tot;
        e[++tot].to = u, e[tot].next = head[v], e[tot].cap = 0, e[tot].flow = 0, e[tot].cost = -cost, head[v] = tot;
    }
    
    bool spfa(int s, int t) {
        deque<int> q;
        for (int i = 0; i <= N; ++i) {
            dis[i] = inf;
            vis[i] = false;
            pre[i] = -1;
        }
        dis[s] = 0;
        vis[s] = true;
        q.push_front(s);
        while (!q.empty()) {
            int u = q.front();
            q.pop_front();
            vis[u] = 0;
            for (int i = head[u]; i; i = e[i].next) {
                int v = e[i].to;
                if (e[i].cap > e[i].flow && dis[v] > dis[u] + e[i].cost) {
                    dis[v] = dis[u] + e[i].cost;
                    pre[v] = i;
                    if (!vis[v]) {
                        vis[v] = true;
                        if (!q.empty()) {
                            if (dis[v] < dis[q.front()]) q.push_front(v);
                            else q.push_back(v);
                        } else q.push_back(v);
                    }
                }
            }
        }
        return pre[t] != -1;
    }
    
    int mcfc(int s, int t, int &cost) {
        cost = 0;
        int flow = 0;
        while (spfa(s, t)) {
            int minn = inf;
            for (int i = pre[t]; i != -1; i = pre[e[i ^ 1].to]) {
                if (minn > e[i].cap - e[i].flow) {
                    minn = e[i].cap - e[i].flow;
                }
            }
            for (int i = pre[t]; i != -1; i = pre[e[i ^ 1].to]) {
                e[i].flow += minn;
                e[i ^ 1].flow -= minn;
                cost += e[i].cost * minn;
            }
            flow += minn;
        }
        return flow;
    }
    
    vector<int> X;
    int A[maxn], B[maxn], C[maxn];
    
    int main() {
        X.clear();
        init(1010);
        int n, k;
        cin >> n >> k;
        for (int i = 0; i < n; i++) {
            cin >> A[i] >> B[i];
            C[i] = B[i] - A[i];
            X.push_back(A[i]);
            X.push_back(B[i]);
        }
    
        //离散化
        sort(X.begin(), X.end());
        X.erase(unique(X.begin(), X.end()), X.end());
    
        int s = 0, t = X.size() - 1;
    
        for (int i = 0; i < t; i++)
            addedge(i, i + 1, inf, 0);
    
        for (int i = 0; i < n; i++) {
            int a = lower_bound(X.begin(), X.end(), A[i]) - X.begin();
            int b = lower_bound(X.begin(), X.end(), B[i]) - X.begin();
            addedge(a, b, 1, -C[i]);
        }
        int ans;
        s = X.size(), t = s + 1;
        addedge(s, 0, k, 0);
        addedge(X.size() - 1, t, k, 0);
        mcfc(s, t, ans);
        cout << -ans << endl;
        return 0;
    }
    

    方法二代码:

    //其余代码与上面相同
    int main() {
        X.clear();
        init(10000);
        int n, k;
        cin >> n >> k;
        for (int i = 0; i < n; i++) {
            cin >> A[i] >> B[i];
            C[i] = B[i] - A[i];
            X.push_back(A[i]);
            X.push_back(B[i]);
        }
    
        //离散化
        sort(X.begin(), X.end());
        X.erase(unique(X.begin(), X.end()), X.end());
        int s = X.size(), t = s + 2, s1 = s + 1;
        addedge(s, s1, k, 0);
    
        for (int i = 0; i < n; i++) {
            int a = lower_bound(X.begin(), X.end(), A[i]) - X.begin();
            int b = lower_bound(X.begin(), X.end(), B[i]) - X.begin();
            addedge(a, b, 1, -C[i]);
            addedge(s1, a, 1, 0);
            addedge(b, t, 1, 0);
            for (int j = 1; j < n; j++) {
                int c = lower_bound(X.begin(), X.end(), A[j]) - X.begin();
                if (b <= c) addedge(b, c, 1, 0);
            }
        }
        int ans;
    
        mcfc(s, t, ans);
        cout << -ans << endl;
        return 0;
    }
    
  • 相关阅读:
    OpenStack对象存储——Swift
    使用ssh对服务器进行登录
    在MacOs上配置Hadoop和Spark环境
    DOTA与面向对象的编程思想(3)——英雄的生命周期
    DOTA与面向对象的编程思想(2)——三层架构,让游戏跑起来
    DOTA与面向对象编程思想(1)——分述DOTA和面向对象思想
    再谈面向对象
    linux C 列出目录中的文件列表 包含文件的相关信息
    在Ubuntu 64位下搭建samba,实现linux与windows之间的资源共享,配置实现Ubuntu启动后samba服务与ssh服务开机自动启动
    LINUX下使用elasticsearch-jdbc工具实现MySQL同步到ElasticSearch 以及linux 64位centos系统安装jdk1.8
  • 原文地址:https://www.cnblogs.com/albert-biu/p/11291644.html
Copyright © 2011-2022 走看看