给定N个带权的开区间,第i个区间覆盖区间(ai,bi),权值为wi。现在要求挑出一些区间使得总权值最大,并且满足实轴上任意一个点被覆盖不超过K次。
1<=K<=N<=200.1<=ai<bi<=100000.1<=wi<=100000.
最小费用最大流。
将所有区间端点离散化到整数1到M,每个数对应一个点。
源点向整数1点连一条容量为K费用为0的边。
整数i点向整数i+1点连一条容量为正无穷费用为0的边。(1<=i<M).
整数M点向汇点连一条容量为正无穷费用为0的边。
每个区间由aai点向bbi点连一条容量为1费用为-wi的边(aai和bbi为区间左右端点离散后的值)。
最小费用最大流取反即为答案。
考虑对于一条aai向bbi的边,费用为负值必然优先选择,使得区间(aai,bbi)剩余流量减一,对应题中(ai,bi)的点剩余覆盖次数减一。注意到本题区间为开区间,所以两个区间相连不影响结果。
1 #include<cstring> 2 #include<cstdio> 3 #include<algorithm> 4 #include<iostream> 5 #include<queue> 6 using namespace std; 7 const int dian=405; 8 const int bian=1505; 9 const int INF=0x3f3f3f3f; 10 int zkh[dian],ykh[dian],khqz[dian]; 11 int zl[dian],yl[dian]; 12 int h[dian],nxt[bian],ver[bian],val[bian],cos[bian],minn[dian],with[dian]; 13 int v[dian],d[dian]; 14 int n,k,tot,bula; 15 int S,T; 16 void add(int a,int b,int c,int d){ 17 tot++;ver[tot]=b;val[tot]=c;cos[tot]=d;nxt[tot]=h[a];h[a]=tot; 18 tot++;ver[tot]=a;val[tot]=0;cos[tot]=-d;nxt[tot]=h[b];h[b]=tot; 19 } 20 bool tell(){ 21 memset(v,0,sizeof(v)); 22 memset(d,0x3f,sizeof(d)); 23 memset(with,0,sizeof(with)); 24 memset(minn,0x3f,sizeof(minn)); 25 queue<int>q; 26 q.push(S); 27 v[S]=1; 28 d[S]=0; 29 while(!q.empty()){ 30 int x=q.front(); 31 q.pop(); 32 v[x]=0; 33 for(int i=h[x];i;i=nxt[i]){ 34 int y=ver[i]; 35 if(d[y]>d[x]+cos[i]&&val[i]){ 36 d[y]=d[x]+cos[i]; 37 minn[y]=min(minn[x],val[i]); 38 with[y]=i; 39 if(!v[y]){ 40 v[y]=1; 41 q.push(y); 42 } 43 } 44 } 45 } 46 if(d[T]==0x3f3f3f3f) 47 return 0; 48 return 1; 49 } 50 int zeng(){ 51 for(int i=T;i!=S;i=ver[with[i]^1]){ 52 val[with[i]]-=minn[T]; 53 val[with[i]^1]+=minn[T]; 54 } 55 return minn[T]*d[T]; 56 } 57 int dinic_cost(){ 58 int r=0; 59 while(tell()) 60 r+=zeng(); 61 return r; 62 } 63 int main(){ 64 int cas; 65 scanf("%d",&cas); 66 while(cas--){ 67 memset(h,0,sizeof(h)); 68 memset(nxt,0,sizeof(nxt)); 69 tot=1; 70 bula=0; 71 scanf("%d%d",&n,&k); 72 for(int i=1;i<=n;i++) 73 scanf("%d%d%d",&zkh[i],&ykh[i],&khqz[i]); 74 //本人太过蒟蒻,下文大段while语句(离散化)不知所云,建议跳过。 75 int hhd; 76 while(1){ 77 hhd=INF; 78 for(int i=1;i<=n;i++) 79 if(hhd>zkh[i]) 80 hhd=zkh[i]; 81 if(hhd==INF) 82 break; 83 bula++; 84 for(int i=1;i<=n;i++) 85 if(hhd==zkh[i]){ 86 if(ykh[i]==INF){ 87 zkh[i]=INF; 88 yl[i]=bula; 89 } 90 else{ 91 zkh[i]=ykh[i]; 92 ykh[i]=INF; 93 zl[i]=bula; 94 } 95 } 96 } 97 S=bula+1,T=bula+2; 98 for(int i=1;i<bula;i++) 99 add(i,i+1,INF,0); 100 add(S,1,k,0); 101 add(bula,T,INF,0); 102 for(int i=1;i<=n;i++) 103 add(zl[i],yl[i],1,-khqz[i]); 104 printf("%d\n",-dinic_cost()); 105 } 106 return 0; 107 }
时间: 2024-10-13 19:44:41