题目大意:给你n个时间段,每个时间段都有一个权值,每个时间段只能选择一次,其中一天时间点能选择互不重叠的时间段,最多选择k次。问怎样选择使得总权值和最大。
和上一题 poj 3680 一样,只是数据输入麻烦点 ;把每个时间段的左右端点拿出来 ,不要重复的 ,按从小到大排序
端点间建边 ,add(i,i+1,k.0) ; 限制一个端点只能选K次 ; 然后对区间建边 ,若有i和j这个时间段,则
add(i,j,1,-w) ,限制区间段只能选一次 ,同时把费用为负 。 源点与第一个点连边,add(s,0,k,0);
最后一个点与汇点连边 ,add(cnt,t,k,0) ;
跑一遍费用流 ,同时取答案的绝对值;
#include<cstdio>
#include<cstring>
#include<map>
#include<vector>
#include<cmath>
#include<cstdlib>
#include<stack>
#include<queue>
#include <iomanip>
#include<iostream>
#include<algorithm>
using namespace std ;
const int N = 5000 ;
const int M = N*3 ;
const int inf = 1<<30 ;
struct node
{
int u ,v,c,cost ,next ;
}edge[M];
struct node1
{
int a,b,w ;
}e[3000] ;
int head[N],pp[N],pre[N],dist[N],vist[N] ;
int top ;
int a[N] ;
void add(int u ,int v,int c,int cost)
{
edge[top].u=u;
edge[top].v=v;
edge[top].c=c;
edge[top].cost=cost;
edge[top].next=head[u];
head[u]=top++;
edge[top].u=v;
edge[top].v=u;
edge[top].c=0;
edge[top].cost=-cost;
edge[top].next=head[v];
head[v]=top++;
}
int SPFA(int s,int t)
{
int u , v ;
memset(vist,0,sizeof(vist));
memset(pre,-1,sizeof(pre));
for(int i = 0 ; i <= t ; i++) dist[i]=inf ;
vist[s]=1;dist[s]=0;pre[s]=s;
queue<int>q;
q.push(s);
while(!q.empty())
{
u=q.front();
q.pop();
vist[u]=0;
for(int i =head[u];i!=-1;i=edge[i].next)
{
v=edge[i].v;
if(edge[i].c && dist[v] > dist[u]+edge[i].cost)
{
dist[v] = dist[u]+edge[i].cost ;
pre[v]=u;
pp[v]=i;
if(!vist[v]);
{
vist[v]=1;
q.push(v);
}
}
}
}
if(dist[t]==inf) return 0;
return 1 ;
}
int MFMC(int s,int t)
{
int mincost=0,flow=0,minflow ;
while(SPFA(s,t))
{
minflow=inf;
for(int i=t;i!=s;i=pre[i])
minflow=min(minflow,edge[pp[i]].c);
for(int i=t;i!=s;i=pre[i])
{
edge[pp[i]].c -= minflow;
edge[pp[i]^1].c += minflow;
}
flow += minflow;
mincost += dist[t]*minflow ;
// printf("****");
}
return -mincost ;
}
int work(char str1[] )
{
int x1,x2,x3,x;
x1= (str1[0]-'0')*10+(str1[1]-'0') ;
x2= (str1[3]-'0')*10+(str1[4]-'0') ;
x3= (str1[6]-'0')*10+(str1[7]-'0') ;
x = (x1*60+x2)*60+x3;
return x ;
}
int main()
{
int n,k ,w;
char str1[10],str2[10] ;
while(~scanf("%d%d",&n,&k))
{ getchar();
top = 0 ;
memset(head,-1,sizeof(head)) ;
int cnt = 0;
for(int i = 1 ; i <= n ; i++)
{
scanf("%s %s %d",&str1,&str2,&w) ;
int x=work(str1) ;
int y=work(str2) ;
e[i].a=x;e[i].b=y;e[i].w=w ;
a[cnt++]=e[i].a,a[cnt++]=e[i].b ;
}
int tmp = 1;
for(int i = 1 ; i < cnt ; i++)
{
if(a[i]!=a[i-1])
a[tmp++]=a[i] ;
}
sort(a,a+tmp) ;
for(int i = 0 ; i < (tmp-1) ; i++)
add(i,i+1,k,0);
for(int i = 1 ; i <= n ; i++)
{
int l = lower_bound(a,a+tmp,e[i].a)-a ;
int r = lower_bound(a,a+tmp,e[i].b)-a ;
add(l,r,1,-e[i].w) ;
}
int s = tmp ,t =tmp+1 ;
add(s,0,k,0);
add(tmp-1,t,k,0);
int ans=MFMC(s,t) ;
printf("%d\n",ans);
}
return 0;
}