zoukankan      html  css  js  c++  java
  • [网络流24题] 最长k可重区间集

    https://www.luogu.org/problemnew/show/3358

    以区间(1,5),(2,6),(7,8)为例

    建模方法一:

    建模方法二:

    离散化区间端点

    相当于找k条费用最大的不相交路径

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    #define N 1011
    #define M 3011
    
    typedef long long LL;
    
    int h[N];
    
    struct node
    {
        int l,r;
    }e[501];
    
    int src,decc;
    
    int front[N],to[M<<1],nxt[M<<1],from[M<<1],cnt=1;
    int cap[M<<1];
    LL cost[M<<1];
    
    LL dis[N];
    int path[N];
    
    bool vis[N];
    
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    
    void add(int u,int v,int w,int val)
    {
        to[++cnt]=v; nxt[cnt]=front[u]; front[u]=cnt; from[cnt]=u; cap[cnt]=w; cost[cnt]=val;
        to[++cnt]=u; nxt[cnt]=front[v]; front[v]=cnt; from[cnt]=v; cap[cnt]=0; cost[cnt]=-val;
    }
    
    bool spfa()
    {
        queue<int>q;
        memset(dis,128,sizeof(dis));
        dis[src]=0;
        vis[src]=true;
        q.push(src);
        int now;
        while(!q.empty())
        {
            now=q.front();
            q.pop();
            vis[now]=false;
            for(int i=front[now];i;i=nxt[i])
            {
                if(cap[i]>0 && dis[to[i]]<dis[now]+cost[i])
                {
                    dis[to[i]]=dis[now]+cost[i];
                    path[to[i]]=i;
                    if(!vis[to[i]])
                    {
                        q.push(to[i]);
                        vis[to[i]]=true;
                    }
                }
            }
        }
        return dis[decc]>0;
    }
    
    int main()
    {
        freopen("interv.in","r",stdin);
        freopen("interv.out","w",stdout);
        int n,k;
        read(n);
        read(k);
        int tot=0;
        for(int i=1;i<=n;++i)
        {
            read(e[i].l);
            read(e[i].r);
            if(e[i].l>e[i].r) swap(e[i].l,e[i].r);
            h[++tot]=e[i].l;
            h[++tot]=e[i].r;
        }
        sort(h+1,h+tot+1);
        tot=unique(h+1,h+tot+1)-h-1;
        for(int i=1;i<=n;++i)
        {
            e[i].l=lower_bound(h+1,h+tot+1,e[i].l)-h;
            e[i].r=lower_bound(h+1,h+tot+1,e[i].r)-h;
        }
        for(int i=1;i<tot;++i) add(i,i+1,1e9,0);
        decc=tot+1;
        add(src,1,k,0);
        add(tot,decc,k,0);
        for(int i=1;i<=n;++i) add(e[i].l,e[i].r,1,h[e[i].r]-h[e[i].l]);
        LL ans=0;
        int now,j;
        while(spfa()) 
        {
            ans+=dis[decc];
            now=decc;
            while(now!=src)
            {
                j=path[now];
                cap[j]--;
                cap[j^1]++;
                now=from[path[now]];
            }
        }
        cout<<ans;
    }

    题目描述

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

    输入输出格式

    输入格式:

    的第 1 行有 2 个正整数 n和 k,分别表示开区间的个数和开区间的可重迭数。接下来的 n行,每行有 2 个整数,表示开区间的左右端点坐标。

    输出格式:

    将计算出的最长 k可重区间集的长度输出

    输入输出样例

    输入样例#1: 复制
    4 2
    1 7
    6 8
    7 10
    9 13 
    输出样例#1: 复制
    15

    说明

    对于100%的数据,1le nle 5001n500,1le kle 31k3

  • 相关阅读:
    观察者模式学习--使用jdk的工具类简单实现
    观察者模式的初始学习--自己实现
    反射 reflect 初始学习
    eclipse java 空心J文件的回复
    linux 命令 more
    spring 3 的 @value的使用
    linux rm 命令
    linux log find 查询
    Resource is out of sync with the file system
    JavaScript(七)数组
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8080899.html
Copyright © 2011-2022 走看看