【HDU】 3572 Task Schedule

Task Schedule


题目链接


题目大意

总共有m个机器,n个任务,每个任务具有Si,Ei,Pi,三种属性,从Si到Ei,总共需要Pi天去完成,每个机器同一时间只能运行一个任务,任务运行时可以被中断去完成其他任务。现在问是否有一种调度方法,使这n个任务能全部完成。


题解

这一题是网络流的题目,难点在于如何建图。

因为每个任务都可以在Si到Ei内任何一个时间运行,我们想到从每个任务向这些可行的时间点建边,又因为每个任务需要运行Pi天,所以我们建立一个源点,向每个任务建立一条长度为Pi的边。每个时间点都可能有任务停止或完成,所以我们从每个时间点向汇点建立一条长度为m的边。

这样,建好图之后我们跑一边DINIC就可以了(本题EK会TLE)


代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>

using namespace std;

int p[505],s[505],e[505],T,n,pre[1005],m,mint,maxt,dis[1005],num,ma[1005][1005];
bool flag[1005];
struct edge
{
    int u,v,d,next;
};
edge E[600010];

bool bfs(int st,int des)
{
    int q[1005],h=0,t=0;
    memset(q,0,sizeof(q));
    memset(dis,0,sizeof(dis));
    q[h++]=st; dis[st]=1;
    while (t!=h)
    {
        int u=q[t++];
        for (int i=pre[u];i!=0;i=E[i].next)
        {
            int v=E[i].v;
            if (!dis[v] && E[i].d)
            {
                dis[v]=dis[u]+1;
                q[h++]=v;
                if (v==des) return 1;
            }
        }
    }
    return 0;
}

int Dinic(int u,int des,int flow)
{
    int ans=0;
    if (u==des) return flow;
    for (int i=pre[u];i!=0;i=E[i].next)
    {
        int v=E[i].v;
        if (E[i].d && dis[v]==dis[u]+1 )
        {
            ans=Dinic(v,des,min(flow,E[i].d));
            if (ans)
            {
                E[i].d-=ans;
                if (ma[v][u]) E[ma[v][u]].d+=ans;
                else
                {
                    E[num].u=v;
                    E[num].v=u;
                    E[num].d=ans;
                    E[num].next=pre[v];
                    pre[v]=num;
                    ma[v][u]=num;
                    num++;
                }
                return ans;
            }
            else dis[v]=0;
        }
    }
    return 0;
}

int main()
{
    int Case=1;
    scanf("%d",&T);
    while(T--)
    {
        int sum=0; num=1; maxt=0; mint=0x7fffffff;
        memset(s,0,sizeof(s));
        memset(p,0,sizeof(p));
        memset(e,0,sizeof(e));
        memset(ma,0,sizeof(ma));
        memset(pre,0,sizeof(pre));
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++)
        {
            scanf("%d%d%d",&p[i],&s[i],&e[i]);
            mint=min(mint,s[i]);
            maxt=max(maxt,e[i]);
            sum+=p[i];
        }
        maxt=maxt-mint+1;
        while (num<=n)
        {
            E[num].u=0;
            E[num].v=num;
            E[num].d=p[num];
            E[num].next=pre[0];
            pre[0]=num;
            ma[0][num]=num;
            num++;
        }
        for (int i=1;i<=n;i++)
            for (int j=s[i]+n;j<=e[i]+n;j++)
        {
            E[num].u=i;
            E[num].v=j;
            E[num].d=1;
            E[num].next=pre[i];
            pre[i]=num;
            ma[i][j]=num;
            num++;
        }
        for (int i=n+1;i<=maxt+n;i++)
        {
            E[num].u=i;
            E[num].v=n+maxt+1;
            E[num].d=m;
            E[num].next=pre[i];
            pre[i]=num;
            ma[i][n+maxt+1]=num;
            num++;
        }
        int ans=0,t;
        while (bfs(0,n+maxt+1))
        {
            while (t=Dinic(0,n+maxt+1,0x7fffffff)) ans+=t;
        }
        printf("Case %d: ",Case++);
        if (ans==sum) printf("Yes\n");
        else printf("No\n");
        printf("\n");
    }
    return 0;
}
时间: 2024-08-04 01:46:56

【HDU】 3572 Task Schedule的相关文章

HDU ACM 3572 Task Schedule 网络最大流-&gt;dinic算法

分析: 建图:每个任务和每一天分别看做一个点,添加源和汇点.源点和每个任务连一条边,每天边的容量为完成对应任务所需处理次数.若第i个任务能够在Si至Ei天处理,则由该任务向这些天分别连一条边,容量为1,表示此任务每天只能被处理一次.最后,每一天分别连一条边到汇点,容量为机器数M,即每天可以处理M个任务.若求出的最大流等于所有任务需要处理的次数之和,说明能完成任务:否则,不能. #include<iostream> #include<vector> #include<queue

hdoj 3572 Task Schedule【最大流】

题目:hdoj 3572 Task Schedule 题意:有m台机器和n个任务,然后给出每个任务的开始时间和结束时间以及需要的天数,让你判断有没有这样条件的安排 分析:网络流题目,比较难想到的是把时间区间怎么在图里面建,其实是在这个区间的每个点都连一条边,建图方案. 超级源点s到每个任务 i 连边,容量为第 i 个任务需要的天数,然后每个任务向满足要求的日期连一条容量为1的边,即从开始到结束都连,然后所有日期到汇点连容量m的边,因为每个机器最多同时能够做m个task. 这样建图发现图中的点最多

HDU 3572 Task Schedule(ISAP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3572 题意:m台机器,需要做n个任务.第i个任务,你需要使用机器Pi天,且这个任务要在[Si  ,  Ei]区间内完成才有效.对于一个任务,只能由一个机器来完成,一个机器同一时间只能做一个任务.当然,一个任务可以分成几段不连续的时间来完成.问,能否做完全部任务. 题意很清晰,也就是判断是否是满流. 对于网络流问题,模板大家都有,关键在于如何建图(详见资料) 思路:今天问了龙哥,对建图有了一定的了解,

hdu 3572 Task Schedule(最大流)

hdu 3572 Task Schedule Description Our geometry princess XMM has stoped her study in computational geometry to concentrate on her newly opened factory. Her factory has introduced M new machines in order to process the coming N tasks. For the i-th tas

hdu 3572 Task Schedule(网络流 dinic算法)

Task Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3412    Accepted Submission(s): 1197 Problem Description Our geometry princess XMM has stoped her study in computational geometry t

【HDU】2147 kiki&#39;s game

http://acm.hdu.edu.cn/showproblem.php?pid=2147 题意:n×m的棋盘,每次可以向左走.向下走.向左下走,初始在(1, m),n,m<=2000,问先手是否胜利. #include <cstdio> using namespace std; int main() { int n, m; while(scanf("%d%d", &n, &m), n|m) (n&1)&&(m&1)?

HDU 4907 BestCoder3_1 Task schedule

Task schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 0    Accepted Submission(s): 0 Problem Description 有一台机器,并且给你这台机器的工作表,工作表上有n个任务,机器在ti时间执行第i个任务,1秒即可完成1个任务.有m个询问,每个询问有一个数字q,表示如果在q时间

【HDOJ】1150 Machine Schedule

匈牙利算法. 1 #include <stdio.h> 2 #include <string.h> 3 4 #define MAXNUM 1005 5 6 char map[MAXNUM][MAXNUM]; 7 char visit[MAXNUM]; 8 int son[MAXNUM]; 9 10 int find(int x, int m) { 11 int i; 12 13 for (i=0; i<m; ++i) { 14 if (!visit[i] &&

【HDU】4923 Room and Moor(2014多校第六场1003)

Room and Moor Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 263    Accepted Submission(s): 73 Problem Description PM Room defines a sequence A = {A1, A2,..., AN}, each of which is either 0