题意:给定n个带权开区间,选择其中一些使得权值最大并且区间重叠层数不超过k。

题解:最小费用流,区间有两百个,可以用左边的点发出一条到右边的点的边,容量为1,费用为负的权值。然后从左往右将依次将相邻的两个点都连起来,权值为0,容量为k,也就是说,如果选了这个区间,就会从费用为负数的边流过去,否则,就是从这个费用为0的边流过去。然后建立一个虚拟源点与最左边的点相连,权值为0,容量为k,这样就保证了重叠数之多为k,因为增广路上所经过的区间必定是不重合的,而流量只有k,所以满足题意。

View Code
  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 }