• 最长可重区间集 spfa费用流


    给定实直线L上的n个开区间,和一个正整数k

    选取若干个区间,在保证实直线L上的任意一个点最多被选出区间覆盖k次的情况下,使得这些区间的长度和最大

    先把区间按照左端点排序,

    考虑到重复其实就代表着相交,

    可以把问题转化为选出k组组内不相交区间,使得他们区间长度和最大。

    从源点S向每个区间左端点连一条容量1费用0的边,每个区间右端点向汇点T连一条容量1费用0的边。用来限制每条边只能选一次。

    每个区间左端点向右端点连一条容量1费用为区间长度的边

    每个区间右端点向所有数值比它大的其他区间左端点连一条容量1费用0的边。

    求最大费用最大流即可。(将所有费用取相反数然后求最小费用最大流)

    代码如下

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const int MAXN=10100;
    const int maxn=1010;
    const int INF=~0U>>1;
    int maxflow=0,cost=0;
    int pre[maxn],vis[maxn],dis[maxn];
    int S,Sa,T;
    int n,k;
    int tot=0;
    int pointer[maxn];
    struct qj{
        int l;int r;
    }a[maxn];
    struct Edge
    {
        int to,next,cap,op,f,w;
        Edge() {};
        Edge(int b,int c,int nxt,int num,int flow,int weight) {to=b,cap=c,next=nxt,op=num^1,f=flow,w=weight;}
    }edge[MAXN];
    inline void addedge(int a,int b,int c,int w1)
    {
        edge[tot]=Edge(b,c,pointer[a],tot,0,w1);
        pointer[a]=tot++;
        edge[tot]=Edge(a,0,pointer[b],tot,0,-w1);
        pointer[b]=tot++;
    }
    bool cmp(qj A,qj B)
    {
        return A.l<B.l;
    }
    void init()
    {
        memset(pointer,-1,sizeof(pointer));
        scanf("%d%d",&n,&k);
        int l,r;
        rep(i,1,n)
        {
            scanf("%d%d",&a[i].l,&a[i].r);
          //  printf("i=%d l=%d r=%d
    ",i,a[i].l,a[i].r);
        }
        sort(a+1,a+n+1,cmp);
        S=0;
        Sa=2*n+1;T=2*n+2;
        addedge(S,Sa,k,0);
        rep(i,1,n)
        {
            addedge(Sa,i,1,0);
            addedge(i,n+i,1,a[i].l-a[i].r);
            rep(j,i+1,n)
            {
                if(a[j].l>=a[i].r)
                {
                    addedge(n+i,j,1,0);
                }
            }
            addedge(n+i,T,1,0);
        }
    }
    bool spfa(int s,int t)
    {
        queue<int > q;
        rep(i,S,T)
        {
            dis[i]=INF;
            vis[i]=false;
            pre[i]=-1;
        }
        dis[S]=0;
        vis[S]=1;
        q.push(S);
        while(!q.empty())
        {
            int u=q.front();q.pop();
            vis[u]=0;
            for(int j=pointer[u];j!=-1;j=edge[j].next)
            {
                int v=edge[j].to;
                if(edge[j].cap-edge[j].f>0&&dis[v]>dis[u]+edge[j].w)
                {
                    dis[v]=dis[u]+edge[j].w;
                    pre[v]=j;
                    if(!vis[v])
                    {
                        vis[v]=1;q.push(v);
                    }
                }
            }
        }
        if(pre[T]==-1) return false;
        else return true;
    }
    int mcmf()
    {
        int flow=0;
        cost=0;
        while(spfa(S,T))
        {
            int mi=INF;
            for(int i=pre[T];i!=-1;i=pre[edge[i^1].to])
            {
                mi=min(mi,edge[i].cap-edge[i].f);
            }
            for(int i=pre[T];i!=-1;i=pre[edge[i^1].to])
            {
                edge[i].f+=mi;
                edge[i^1].f-=mi;
                cost+=edge[i].w*mi;
            }
            flow+=mi;
        }
        return flow;
    }
    int main()
    {
        freopen("interv0.in","r",stdin);
      //  freopen("why.txt","w",stdout);
        init();
        mcmf();
        printf("%d",-cost);
        return 0;
    }
  • 相关阅读:
    索引
    运算符优先级
    身份运算符
    成员运算符
    位运算符
    利用java编写物品的品牌、尺寸、价格、库存(新手)
    今天聊一聊nuxt.js(上)
    初入前端,面对一个项目应注意哪些?
    小型 Web 页项目打包优化方案
    跨域的那些事儿
  • 原文地址:https://www.cnblogs.com/zhixingr/p/7612307.html
Copyright © 2020-2023  润新知