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

    洛谷传送门 LOJ传送门

    很巧妙的建图啊...刚了$1h$也没想出来,最后看的题解

    发现这道题并不类似于我们平时做的网络流题,它是在序列上的,且很难建出来二分图的形。

    那就让它在序列上待着吧= =

    对于一个区间,左端点向右端点连边,流量为$1$,费用为区间长度

    对于一个位置$i$,向$i+1$连边,流量为$K$,费用为$0$

    为什么要这么建图呢?

    假设有$1$流量流到了位置$i$,有两种情况

    1.选择一个从i开始的区间$[i,r]$,这点流量流到了$r$位置。而在$(i,r)$内,这点流量不能用于其它区间,达到了限制区间个数的目的,然后我们获得了$r-i$点收益

    2.不选任何区间,流量流到了$i+1$位置,为后面的区间提供流量

    然后跑最大费用最大流就行了

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define N1 2005
     5 #define M1 100100
     6 #define ll long long
     7 #define dd double
     8 #define inf 0x3f3f3f3f
     9 using namespace std;
    10 
    11 int gint()
    12 {
    13     int ret=0,fh=1;char c=getchar();
    14     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
    15     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
    16     return ret*fh;
    17 }
    18 int n,K,S,T;
    19 struct Edge{
    20 int head[N1],to[M1<<1],nxt[M1<<1],flow[M1<<1],dis[M1<<1],cte;
    21 void ae(int u,int v,int F,int D)
    22 {
    23     cte++; to[cte]=v; flow[cte]=F; dis[cte]=D;
    24     nxt[cte]=head[u]; head[u]=cte;
    25 }
    26 }e;
    27 
    28 int que[M1<<1],hd,tl,dis[N1],id[N1],flow[N1],use[N1];
    29 int spfa()
    30 {
    31     int x,j,v;
    32     memset(dis,-1,sizeof(dis)); memset(flow,0,sizeof(flow)); memset(use,0,sizeof(use));
    33     hd=1,tl=0; que[++tl]=S; dis[S]=0; use[S]=1; flow[S]=inf;
    34     while(hd<=tl)
    35     {
    36         x=que[hd++]; 
    37         for(j=e.head[x];j;j=e.nxt[j])
    38         {
    39             v=e.to[j]; 
    40             if( e.flow[j]>0 && dis[v]<dis[x]+e.dis[j] )
    41             {
    42                 dis[v]=dis[x]+e.dis[j]; 
    43                 flow[v]=min(flow[x],e.flow[j]);
    44                 que[++tl]=v; id[v]=j; use[v]=1;
    45             }
    46         }
    47         use[x]=0;
    48     }
    49     return dis[T]!=-1;
    50 }
    51 int EK()
    52 {
    53     int tcost=0,mxflow=0,x;
    54     while(spfa())
    55     {
    56         mxflow+=flow[T]; tcost+=flow[T]*dis[T];
    57         for(x=T;x!=S;x=e.to[id[x]^1])
    58         {
    59             e.flow[id[x]]-=flow[T]; 
    60             e.flow[id[x]^1]+=flow[T]; 
    61         }
    62     }
    63     return tcost;
    64 }
    65 
    66 int l[N1],r[N1],len[N1],t[N1<<1],cnt;
    67 int main()
    68 {
    69     scanf("%d%d",&n,&K); 
    70     int i,j,x,y,ma; e.cte=1;
    71     for(i=1;i<=n;i++)
    72     {
    73         l[i]=gint(),r[i]=gint()-1; if(l[i]>r[i]) swap(l[i],r[i]); 
    74         t[++cnt]=l[i]; t[++cnt]=r[i]; len[i]=r[i]-l[i]+1;
    75     } 
    76     sort(t+1,t+cnt+1); cnt=unique(t+1,t+cnt+1)-(t+1);
    77     for(i=1;i<=n;i++) l[i]=lower_bound(t+1,t+cnt+1,l[i])-t;
    78     for(i=1;i<=n;i++) r[i]=lower_bound(t+1,t+cnt+1,r[i])-t;
    79     S=0; T=cnt+1;
    80     for(i=1;i<=n;i++) e.ae(l[i],r[i]+1,1,len[i]), e.ae(r[i]+1,l[i],0,-len[i]);
    81     for(i=1;i<=cnt;i++) e.ae(i,i+1,K,0), e.ae(i+1,i,0,0); e.ae(S,1,K,0); e.ae(1,S,0,0);
    82     printf("%d
    ",EK()); 
    83     return 0;
    84 }
  • 相关阅读:
    【新特性速递】数字输入框的前缀和后缀(位于输入框内部)
    【新特性速递】进度条,进度条,进度条
    【新特性速递】当法语遇上FineUI(Bonjour)!
    【新特性速递】自定义数字输入框的小数分隔符和千分位分隔符
    【经验分享】FineUICore中如何处理文件导出异常?
    【网友作品】服装分销系统架构与界面分享(基于FineUICore基础版)
    FineUIPro/Mvc/Core v6.3.0 正式发布了!
    星球居民突破 1700 人!
    【新特性速递】开关样式复选框增强!
    【新特性速递】为RenderField新增QuickSortField属性!
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10291765.html
Copyright © 2011-2022 走看看