POJ 3680

题意:给定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 }

你可能感兴趣的:(poj)