百度蝌蚪团

这次百度的题目中,这个属于稍微有点难度的。

F:百科蝌蚪团

时间限制: 
1000ms 
内存限制: 
65536kB
描述

百度百科有一支神奇的队伍,他们叫自己“百科蝌蚪团”。为了更好的让蝌蚪团的成员们安排工作,百度百科的运营团队定出了一个24小时制的时间表。例如:
1.    每个蝌蚪团成员工作时长相同;
2.    必须安排蝌蚪团成员在他们方便的时间段工作;
3.    蝌蚪团成员安排时间最小安排时间节点(开始工作或停止工作)为半小时,比如04:00或04:30,而不是04:15;
4.    蝌蚪团成员一天在百度百科工作的时间是有上限的,他们会根据自己的情况给出上限。
5.    在特定时间段内必须有一定数量的蝌蚪团成员工作,以保证百度百科不断的进步
请帮运营团队计算一下,能保持24小时稳定在岗的蝌蚪团最少成员的数量。如果有2个蝌蚪团成员工作结束,同时另2个蝌蚪团成员开始工作,这段时间都算有2各成员稳定在岗。

输入
输入有多组,每组测试数据以一个整数N开头(1 ≤ N ≤ 50),表示蝌蚪团的成员数。紧接着,我们会有N个数据块,每一个数据块对应了一名蝌蚪团成员的日程情况。

每个数据块以两个整数开始,分别为K(1 ≤ K ≤ 50)和M(1 ≤ M ≤ 1440),用空格隔开。K表示这个数据块对应蝌蚪团成员方便的时间段的数量,M表示这个成员愿意每天在百度百科工作的最长分钟数。接下去的K行中,每行包括两个时间,分别表示成“HH:MM”的格式,以空格分隔,分别对应了该蝌蚪团成员一个方便的时间段的开始时间、结束时间;例如09:00 10:00表明他在早上九点到十点的时间段是方便的,可以在百度百科工作。如果两个时间相同,则说明这个他全天都是方便的。

最后一组数据的N为0,表示输入结束。

输出
对于每组数据,输出为一个整数,占一行。表示能保持24小时稳定在岗的蝌蚪团最少成员的数量。
样例输入
5
1 720
18:00 12:00
1 1080
00:00 23:00
1 1080
00:00 20:00
1 1050
06:00 00:00
1 360
18:00 00:00
3
1 540
00:00 00:00
3 480
08:00 10:00
09:00 12:00
13:00 19:00
1 420
17:00 00:00
3
1 1440
00:00 00:00
1 720
00:00 12:15
1 720
12:05 00:15
0
样例输出
2
1
1


这个题目稍微有点经验的人,就能够看出是最大流的问题。我先贴下我的Edmonds_Karp算法

#include <iostream>
#include<stdio.h>
#include<cstring>
using namespace std;
#define min(a,b) a<b?a:b;
int map[110][110];
int cur[110][110];
int me(int x)
{
    if(x==0) return 0;
    else return 1;
}
bool max(int s,int d)
{
    int queue[200],pre[200],tmp[200];
    int sum=0;
    memset(cur,0,sizeof(cur));
    while(true)
    {
    int size=0,point=-1;
    queue[0]=s;
    size++;
    point++;
    memset(tmp,0,sizeof(tmp));
    pre[0]=0xffff;
    tmp[0]=0xffff;
    while(point<size)
    {
        int m=queue[point];
         point++;
        for(int i=1;i<=d;i++)
        {
            if(cur[m][i]<map[m][i]&&!tmp[i])
            {
                queue[size++]=i;
                pre[i]=m;
                tmp[i]=min(tmp[m],map[m][i]-cur[m][i]);
            }
        }
    }
     if(tmp[d]==0) break;
     for(int i=d;i!=s;i=pre[i])
     {
          cur[pre[i]][i]+=tmp[d];
          map[i][pre[i]]+=tmp[d];
     }
     sum+=tmp[d];
    }
       if(sum<map[51][99]*48)
            return false;
       else  return true;
}
int main()
{
    int N,p=1;
    while(cin>>N&&N)
    {
        p=1;
        memset(map,0,sizeof(map));
        while(N--)
        {
             int k,m;
        cin>>k>>m;
        map[0][p]=m/30;
        for(int i=0;i<k;i++)
        {
            int a,b,c,d;
            scanf("%d:%d %d:%d",&a,&b,&c,&d);
            if(a==c&&b==d)
            {
                for(int j=51;j<99;j++)
                    map[p][j]=1;
            }
            else if(a*60+b>c*60+d)
            {
                    for(int j=2*a+1+me(b)+b/30;j<=48;j++)
                        map[p][50+j]=1;
                    for(int j=1;j<2*c+d/30+1;j++)
                        map[p][50+j]=1;
            }
            else
            {
                     for(int j=2*a+1+me(b)+b/30;j<2*c+d/30+1;j++)
                        map[p][50+j]=1;
            }
        }
        p++;
        }
        int start=0,end=50;
        while((end+start)/2>start)
        {
            int k=(start+end)/2;
            for(int i=51;i<99;i++)
            map[i][99]=k;
            if(max(0,99))
            {
                start=k;
            }
            else end=k;
        }
        cout<<start<<endl;
    }
    return 0;
}

好吧,结果超时了,意料之中的,毕竟这种方法在最大流中属于很慢的。我们再来看看另一个算法:

点赞