题意:
给你每个任务的时间段和它的任务得分,再给你你所拥有的天数,问在这有限的天数里怎么安排时间才能的最多的分。
题解:
和3680一样的建图方法。离散化一下,每个点之间连边,容量无穷费用为零。某个任务时间段的两端点连边,容量为1,费用为任务得分。源点与第一个点相连,容量为天数,费用为零。
之所以每个点都连一条边并且容量无穷费用为零,是使之就像一个分叉路口一样,如果你要做这个时间点上的任务,那你就走时间段那条边,但如果你不做这个时间点上的任务,为了确保你还可以沿着时间继续走下去,所以建了一条容量为无穷费用为零的边。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MX 10000000
#define nMax 100000
#define eMax 100000
using namespace std;
int time[90000];
struct Task{
int st,ed,numb;
}task[2222];
struct Egde{
int u,v,c,f,w,next,pre; // u起点 v终点 c容量 f流量 w费用 next下一条边 pre反边
}eg[eMax];
int N, K, ans,e,vs,vt;
int k, list[nMax],time1[nMax];
int que[10000000], pre[nMax], dis[nMax];
bool vis[nMax];
void add(int u, int v, int c, int w){//u起点,v终点,c容量,w费用
eg[k].u=u;eg[k].v=v;eg[k].pre=k+1;eg[k].next=list[u];eg[k].c=c;eg[k].f=0;eg[k].w=w;list[u]=k++;
eg[k].u=v;eg[k].v=u;eg[k].pre=k-1;eg[k].next=list[v];eg[k].c=0;eg[k].f=0;eg[k].w=-w;list[v]=k++;
}
int min(int a,int b){
return a<b?a:b;
}
bool spfa(){ // 源点为0,汇点为n。
int i, head = 0, tail = 1;
for(i = vs; i <= vt; i ++){//源点到汇点初始化
dis[i] = MX;
vis[i] = false;
}
dis[vs] = 0;
que[0] = vs;
vis[vs] = true;
while(tail > head){ // 这里最好用队列,有广搜的意思,堆栈像深搜。
int u = que[head ++];
for(i = list[u]; i != -1; i = eg[i].next){
int v = eg[i].v;
if(eg[i].c-eg[i].f && dis[v] > dis[u] + eg[i].w){
dis[v] = dis[u] + eg[i].w;
pre[v] = i;
if(!vis[v]){
vis[v] = true;
que[tail ++] = v;
}
}
}
vis[u] = false;
}
// printf("! dis=%d\n",dis[vt]);
if(dis[vt] == MX) return false;//如果汇点为MX那么没有最短路了
return true;
}
void end(){
int u, p, sum = MX;
for(u = vt; u != vs; u = eg[eg[p].pre].v){//寻找最大流
p = pre[u];
sum = min(sum, eg[p].c-eg[p].f);
}
for(u = vt; u != vs; u = eg[eg[p].pre].v){//更改流量,并算出最小费用
p = pre[u];
eg[p].f += sum;
eg[eg[p].pre].f -= sum;
ans += sum * eg[p].w;
}
}
int main(){
while(scanf("%d%d",&N,&K)!=EOF){
memset(list,-1,sizeof(list));
k=0;
e=0;
char s[20];
for(int i=0;i<N;i++){
scanf("%s",s);
time[e++]=task[i].st=((s[0]-'0')*10+(s[1]-'0'))*3600+((s[3]-'0')*10+(s[4]-'0'))*60+((s[6]-'0')*10+(s[7]-'0'));
scanf("%s",s);
time[e++]=task[i].ed=((s[0]-'0')*10+(s[1]-'0'))*3600+((s[3]-'0')*10+(s[4]-'0'))*60+((s[6]-'0')*10+(s[7]-'0'));
scanf("%d",&task[i].numb);
}
sort(time,time+e);
int ee=1;
memset(time1,-1,sizeof(time1));
for(int i=0;i<e;i++){
if(time1[time[i]]==-1){
time1[time[i]]=ee++;
}
}
for(int i=1;i<ee-1;i++){
add(i,i+1,MX,0);
}
add(0,1,K,0);
for(int i=0;i<N;i++){
add(time1[task[i].st],time1[task[i].ed],1,-task[i].numb);
}
// for(int i=0;i<k;i++){
// printf("! u=%d v=%d c=%d w=%d \n",eg[i].u,eg[i].v,eg[i].c,eg[i].w);
// }
vs=0;vt=ee-1;
ans = 0;
while(spfa()) end();
printf("%d\n",-ans);
}
return 0;
}