[网络流24题] 最长k可重区间集问题 (费用流)
很巧妙的建图啊...刚了$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\n",EK()); 83 return 0; 84 }