hdu3572Task Schedule 最大流,判断满流 优化的SAP算法

  PS:多校联赛的题目质量还是挺高的。建图不会啊,看了题解才会的。

  参考博客:http://blog.csdn.net/luyuncheng/article/details/7944417

  看了上面博客里的题解,思路就有了。不过建图还是有点麻烦。我把源点设为n+1 (不想从0开始,不修改模版),汇点就是n+2+MAX,其中MAX是题目中Ei的最大值。

  这题,我有疑问:优化过的SAP算法的时间复杂度是O(m*n^2),此题的n最大为1000,m为50万,时间超过5亿了。1s的时限居然过了。

  其中有个小插曲,我想了好久才明白的。为什么是判断满流,最后一定要用 “==”? >=不可以么?最后想明白了,其实求出来的最大流的值一定是<= sum的。因为从源点出来的流值最大也才sum。  

  下面是代码:  建图会了用模版就可以了。模版参考哈工大的《图论及应用》。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=1010,M=510000, INF=0x3f3f3f3f;
struct node
{
    int to,next,w;
}edge[M];
int head[N],numh[N],h[N],cure[N],pre[N];
//numh:GAP优化的统计高度数量数组; h:距离标号数组; cure:当前弧
int ans,tot;
void SAP(int s, int e,int n)
{
    int flow,u,tmp,neck,i;
    ans=0;
    for(i=1;i<=n;i++)
        cure[i]=head[i];
    numh[0]=n;
    u=s;
    while(h[s]<n)
    {
        if(u==e)
        {
            flow =INF;
            for(i=s;i!=e;i=edge[cure[i]].to)
            {
                if(flow>edge[cure[i]].w)
                {
                    neck=i;
                    flow =edge[cure[i]].w;
                }
            }
            for(i=s;i!=e;i=edge[cure[i]].to)
            {
                tmp=cure[i];
                edge[tmp].w-=flow;
                edge[tmp^1].w+=flow;
            }
            ans+=flow;
            u=neck;
        }
        for(i=cure[u];i!=-1;i=edge[i].next)
            if(edge[i].w && h[u]==h[edge[i].to]+1) break;
        if(i!=-1) {cure[u]=i;pre[edge[i].to]=u;u=edge[i].to;}
        else
        {
            if(0==--numh[h[u]]) break; //GAP优化
            cure[u]=head[u];
            for(tmp=n,i=head[u];i!=-1;i=edge[i].next)
                if(edge[i].w) tmp=min(tmp, h[edge[i].to]);
            h[u]=tmp+1;
            ++numh[h[u]];
            if(u!=s) u=pre[u];
        }
    }
}
void init()
{
    tot=0;
    memset(head,-1,sizeof(head));
    memset(pre,-1,sizeof(pre));
    memset(h,0,sizeof(h));
    memset(numh,0,sizeof(numh));

}
void addedge(int i,int j,int w)
{
    edge[tot].to=j;edge[tot].w=w;edge[tot].next=head[i];head[i]=tot++;
    edge[tot].to=i;edge[tot].w=0;edge[tot].next=head[j];head[j]=tot++;
}
int main()
{
    //freopen("test.txt","r",stdin);
    int n,m,i,j,k,cas,t=1,a,b,c,MAX,sum,s;
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d%d",&n,&m);
        init();
        MAX=0;sum=0;s=n+1;
        for(i=1;i<=n;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            sum+=a;
            MAX=max(MAX,c);
            addedge(s,i,a);
            for(j=b;j<=c;j++)
                addedge(i,j+s,1);
        }
        k=s+1+MAX;
        for(i=1;i<=MAX;i++)
            addedge(s+i,k,m);
        SAP(s,k,k);
        printf("Case %d: ",t++);
        if(ans==sum) printf("Yes\n\n");
        else printf("No\n\n");
    }
    return 0;
}

时间: 2024-08-24 06:22:14

hdu3572Task Schedule 最大流,判断满流 优化的SAP算法的相关文章

hdu3572 任务分配/最大流判断满流

题意:将n个任务分配为m个机器,给每个任务需要的天数(无需每天连续),和可以在哪些天去做该任务,求是否存在方案. 典型的任务(X)----天(Y)二分最大流,(因为这里任务是与天的关系)处理器控制流量,源点向X部点,指需要的天数,任务xi,向可以做的天连,流量1,每个Y部点向汇点连流量为m,表示该天最多用M个机器. ps:注意输出格式 #include<iostream> #include<queue> #include<cstdio> #include<cstr

hdu-3572 Task Schedule---最大流判断满流+dinic算法

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3572 题目大意: 给N个任务,M台机器.每个任务有最早才能开始做的时间S,deadline E,和持续工作的时间P.每个任务可以分段进行,但是在同一时刻,一台机器最多只能执行一个任务. 问存不存在可行的工作时间. 解题思路: 由于时间<=500且每个任务都能断断续续的执行,那么我们把每一天时间作为一个节点来用网络流解决该题. 建图: 源点s(编号0), 时间1-500天编号为1到500, N个任务

HDU 3572 Task Schedule(最大流判断满流)

https://vjudge.net/problem/HDU-3572 题意: 有N个作业和M台机器,每个作业都有一个持续时间P,工作的日期为S~E.作业可以断断续续的在不同机器上做,每台机器每次只可以处理一个作业.判断是否可以在作业的工作日期内完成所有作业. 思路: 建立源点0和汇点t,因为天数最多为500,所有我们将日期的编号定为1~500,作业的编号为500+i. 对于每个作业,与源点0相连,容量为P,意味着它必须走完这P容量才能完成这作业.与S~E相连,容量为1.日期与汇点相连,容量为m

hdu2883 最大流,判断满流 优化的SAP算法

这是09年的多校联赛题目,比10年的难度要大.如果没做过hdu3572,建议先去做.有了解题思维再来做这题. 这题与hdu3572类似.但是1 <= si < ei <= 1,000,000的限制使得我们如果像HDU3572那样建图,会使得边的数量太多.从而超时. 看看别人的题解 http://www.cnblogs.com/wally/archive/2013/05/03/3057066.html  离散化的思想 #include<iostream> #include<

hdu 4940 Destroy Transportation system( 无源汇上下界网络流的可行流判断 )

题意:有n个点和m条有向边构成的网络,每条边有两个花费: d:毁坏这条边的花费 b:重建一条双向边的花费 寻找这样两个点集,使得点集s到点集t满足 毁坏所有S到T的路径的费用和 > 毁坏所有T到S的路径的费用和 + 重建这些T到S的双向路径的费用和. 思路1: 然后这个无源汇带上下界网络流的可行流问题的求解方法见这里~~ 建图就是上面说的那样啦~最后判断有没有可行流就是求一下我们所构造的这个新的网络的最大流~然后判断一下这个最大流是否满流~(即判断最大流是否和附加源点的流出总量相等~~) cod

(二分最大流) 最大流 + 二分查找 小结

做最大流题目的时候会遇到一种需要用二分查找的题型: (poj2455) 一张无向图中有 N 个点,M 条边,每条边都有一个权值,且每条边只能用一次,要求找出 T 条从 1 到 N 的路径,使这 T 条路径所经过的边中,权值的最大值最小. 转化为最大流模型:T就是最大流,每条边只能用一次在网络流中就是容量为1.然后二分查找(枚举),边权小于或等于mid的边就加一条容量为1的网络流的边.最后知道最大流ans与T相等的最小的mid就是所求. 在二分查找的时候,与一般的二分查找还是有区别的,一般不能有“

hdu3572--Task Schedule(最大流+两种优化方法,dinic)

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

hdoj 4888 Redraw Beautiful Drawings 【最大流满流+唯一性判断】

题目:hdoj 4888 Redraw Beautiful Drawings 分类:最大流满流 , 最大流唯一性 来源:2014 Multi-University Training Contest 3 题意:一个矩阵的每行每列的和都知道,然后让你求能不能填,是否唯一,唯一的话输出解. 分析:这个题目能看出来是最大流,但是难点有2. 首先:题中矩阵400 * 400 ,好在题目中矩阵和没有特殊要求,所以可以直接以行列建图,建图方案: 1. 源点 -> 每一行对应的点,流量限制为该行的和 2. 每一

HDU3572Task Schedule(最大流 ISAP比较快)建图方法不错

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