题意:给定n个带权开区间,选择其中一些使得权值最大并且区间重叠层数不超过k。
题解:最小费用流,区间有两百个,可以用左边的点发出一条到右边的点的边,容量为1,费用为负的权值。然后从左往右将依次将相邻的两个点都连起来,权值为0,容量为k,也就是说,如果选了这个区间,就会从费用为负数的边流过去,否则,就是从这个费用为0的边流过去。然后建立一个虚拟源点与最左边的点相连,权值为0,容量为k,这样就保证了重叠数之多为k,因为增广路上所经过的区间必定是不重合的,而流量只有k,所以满足题意。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<queue> 5 using namespace std; 6 const int N=500,M=1000; 7 const int inf=1<<29; 8 int head[N],nc; 9 struct Edge 10 { 11 int x,y,next; 12 int cap,cost; 13 } edge[M*3]; 14 void add(int x,int y,int cap,int cost) 15 { 16 edge[nc].x=x; 17 edge[nc].y=y; 18 edge[nc].cap=cap; 19 edge[nc].next=head[x]; 20 edge[nc].cost=cost; 21 head[x]=nc++; 22 edge[nc].x=y; 23 edge[nc].y=x; 24 edge[nc].cap=0; 25 edge[nc].next=head[y]; 26 edge[nc].cost=-cost; 27 head[y]=nc++; 28 } 29 int dist[N],pe[N],pv[N]; 30 bool mark[N]; 31 int mincost(int n) 32 { 33 int S=0,T=n-1,flow=0,cost=0,mxf,i,j,k; 34 while(1) 35 { 36 for(i=0;i<n;i++) 37 dist[i]=inf; 38 memset(mark,false,sizeof(mark)); 39 queue<int> Q; 40 Q.push(S); 41 mark[S]=true; 42 dist[S]=0; 43 while(!Q.empty()) 44 { 45 int now=Q.front(); 46 Q.pop(); 47 mark[now]=false; 48 for(i=head[now];i!=-1;i=edge[i].next) 49 { 50 Edge x=edge[i]; 51 if(x.cap&&dist[x.y]>x.cost+dist[now]) 52 { 53 dist[x.y]=x.cost+dist[now]; 54 pe[x.y]=i; 55 pv[x.y]=now; 56 if(!mark[x.y]) 57 { 58 mark[x.y]=true; 59 Q.push(x.y); 60 } 61 } 62 } 63 } 64 if(dist[T]==inf) 65 return cost; 66 for(k=T,mxf=inf;k!=S;k=pv[k]) 67 mxf=min(mxf,edge[pe[k]].cap); 68 flow+=mxf;cost+=dist[T]*mxf; 69 for(k=T;k!=S;k=pv[k]) 70 edge[pe[k]].cap-=mxf,edge[pe[k]^1].cap+=mxf; 71 } 72 } 73 int data[N][3],ar[N]; 74 int lisan[100005]; 75 int main() 76 { 77 int T; 78 for(scanf("%d",&T);T;T--) 79 { 80 int num,i,j,k,n=1; 81 memset(lisan,-1,sizeof(lisan)); 82 memset(head,-1,sizeof(head)); 83 nc=0; 84 scanf("%d%d",&num,&k); 85 for(i=0;i<num;i++) 86 scanf("%d%d%d",&data[i][0],&data[i][1],&data[i][2]),ar[n++]=data[i][0],ar[n++]=data[i][1]; 87 sort(ar+1,ar+n); 88 for(i=2,j=1;i<n;i++) 89 if(ar[j]!=ar[i]) 90 ar[++j]=ar[i]; 91 n=j+1; 92 add(0,1,k,0); 93 for(i=1;i<n;i++) 94 { 95 lisan[ar[i]]=i; 96 add(i,i+1,k,0); 97 } 98 for(i=0;i<num;i++) 99 add(lisan[data[i][0]],lisan[data[i][1]],1,-data[i][2]); 100 printf("%d\n",-mincost(n)); 101 } 102 return 0; 103 }