POJ3762 时间段用k次

题意:
      有n个任务,每个任务有自己的开始时间和结束时间,还有完成这个任务能获得的价值,然后每一天的同一个时刻只能执行一个任务,每个任务必须连续执行完成,最多可以工作m天,问这m天能获得的最大价值。


思路:
      一开始没想太多,直接建立一个图,然后TLE了,先说下我TLE的那个吧!,逻辑上应该没错,是时间过不起,我是先把每一个点差点,拆成两个,流量1,费用是他的价值,然后虚拟出来一个点,连接所有点,流量是1,意思是所有点都可以作为这一天的开始,然后每一个点都连接干完这个活之后可以在干的另一个活,流量是1,费用0,最后所有的点在连接终点,流量1,费用0,意思是每一个点都可以作为这一天的最后一个任务,然后在超级源点那在虚拟出来一个点,和起点连接,流量m费用0,意思最多可以干m天,结果TLE了,现在说下官方题解,官方题解也非常简单容易理解,是这样的,我们可以吧所有涉及的时间点都拿出来,然后sort离散化一下,然后得到一个<=n*2的点集,(<是因为可能有重复的时间点),把这一串点集全都连接上,i->i+1 流量是INF,费用是0,这样的目的是任意两个任务之间虽然没有交集,但是也可以用0花费连接起来,然后对于每一个任务,他的起点和终点都对应着离散化之后的某两个点,然后把这两个点之间俩接一条边,流量1,费用是这个任务的价值,最后再在第一个点之前虚拟出来一个点s连接第一个点,流量是m费用是0,限制天数用的,然后在在最后一个离散化后的点连接一个虚拟的t(这个虚拟的t可以不用,我个人习惯,于是就用了),最后一遍费用流就行了。官方的这个做法的边数是n的,我的那个是n*n的,n的这个我的都跑了1300多了,n*n的必然TLE了。


#include<map>
#include<queue>
#include<stdio.h>
#include<string.h>
#include<algorithm>


#define N_node 5000
#define N_edge 50000
#define INF 1000000000


using namespace std;


typedef struct
{
   int from ,to ,next ,cost ,flow;
}STAR;


typedef struct
{
   int a ,b ,c;
}NODE;


STAR E[N_edge];
NODE node[2200];
int list[N_node] ,tot;
int mer[N_node] ,s_x[N_node] ,mark[N_node];
int num[N_node];
map<int ,int>hash;




void add(int a ,int b ,int c ,int d)
{
   E[++tot].from = a;
   E[tot].to = b;
   E[tot].cost = c;
   E[tot].flow = d;
   E[tot].next = list[a];
   list[a] = tot;
   
   E[++tot].from = b;
   E[tot].to = a;
   E[tot].cost = -c;
   E[tot].flow = 0;
   E[tot].next = list[b];
   list[b] = tot;
}


bool Spfa(int s ,int t ,int n)
{
   for(int i = 0 ;i <= n ;i ++)
   s_x[i] = -INF ,mark[i] = 0;
   queue<int>q;
   s_x[s] = 0 ,mark[s] = 1;
   q.push(s);
   memset(mer ,255 ,sizeof(mer));
   while(!q.empty())
   {
      int xin ,tou;
      tou = q.front();
      q.pop();
      mark[tou] = 0;
      for(int k = list[tou] ;k ;k = E[k].next)
      {
         xin = E[k].to;
         if(s_x[xin] < s_x[tou] + E[k].cost && E[k].flow)
         {
            s_x[xin] = s_x[tou] + E[k].cost;
            mer[xin] = k;
            if(!mark[xin])
            {
               mark[xin] = 1;
               q.push(xin);
            }
         }
      }
   }
   return mer[t] != -1;
}


int M_C_Flow(int s ,int t ,int n)
{
   int minflow ,maxflow = 0 ,maxcost = 0;
   while(Spfa(s ,t ,n))
   {
      minflow = INF;
      for(int i = mer[t] ;i + 1 ;i = mer[E[i].from])
      if(minflow > E[i].flow) minflow = E[i].flow;
      for(int i = mer[t] ;i + 1 ;i = mer[E[i].from])
      {
         E[i].flow -= minflow;
         E[i^1].flow += minflow;
         maxcost += minflow * E[i].cost;
      }
      maxflow += minflow;
   }
   return maxcost;
}


int main ()
{
   int i ,j ,n ,m;
   int a ,b ,c ,aa ,bb ,cc ,d;
   while(~scanf("%d %d" ,&n ,&m))
   {
      memset(list ,0 ,sizeof(list)) ,tot = 1;
      int nowid = 0;
      for(i = 1 ;i <= n ;i ++)
      {
         scanf("%d:%d:%d %d:%d:%d %d" ,&a ,&b ,&c ,&aa ,&bb ,&cc ,&d);
         node[i].a = c*1+b*60+a*3600;
         node[i].b = cc*1+bb*60+aa*3600;
         node[i].c = d;
         num[++nowid] = node[i].a;
         num[++nowid] = node[i].b;
      }
      sort(num + 1 ,num + nowid + 1);
      int now = 0;
      for(i = 1 ;i <= nowid ;i ++)
      {
         if(i == 1 || num[i] != num[i-1]) now ++;
         hash[num[i]] = now;
      }
      memset(list ,0 ,sizeof(list)) ,tot = 1;
      add(0 ,1 ,0 ,m);
      for(i = 2 ;i <= now ;i ++)
      add(i - 1 ,i ,0 ,INF);
      add(now ,now + 1 ,0 ,m);
      for(int i = 1 ;i <= n ;i ++)
      add(hash[node[i].a] ,hash[node[i].b] ,node[i].c ,1);
      int Ans = M_C_Flow(0 ,now + 1 ,now + 1);
      printf("%d\n" ,Ans);
   }
   return 0;
}
         
        
      
      
         
      
      
      
   
 
   
   
   




   







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值