HDU 2883 kebab(最大流,满流)

题意:有一个人有个烤架,他的烤架同时可以烤m个串,有n个顾客会过来买,si,ni,ei,ti分别表示当前顾客来的开始时间,需要烤串的数量,最晚走的时间,每个烤串需要烤的时间。
思路:此题同 HDU 3572,比3572多一个离散化
s->时间->顾客->t
因为此题时间范围太大,所以需要离散化,然后时间是一个区间
比如说测试数据1的图如下:
2 10
1 10 6 3
2 10 4 2
这里写图片描述

边上的的值是容量(图画的太丑,请凑合看)

顺便说一下模板的事,此模板是从q神处学习,q神博客
此处说下我对这个模板
ISAP的实现过程和优化 http://www.renfei.org/blog/isap.html
首先是BFS
此模板的BFS是由第三部分和第一部分实现,具体实现读者可以自行printf(“%d(%d) “,dep[i],gap[i])(1<=i<=n)
其他和上述链接并无他样
gap[i]是标记当前距离为i的点的数量
pre是此点的钱一个点的标号,为了走到汇点,然后返回+-边流量
dep[i]是点i的距离

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<queue>
#include<stack>
#include<string>
#include<vector>
#include<map>
#include<set>
using namespace std;
#define rfor(i,a,b) for(i=a;i<=b;i++)
#define lfor(i,a,b) for(i=a;i>=b;i--)
#define sfor(i,a,h) for(i=h[a];i!=-1;i=e[i].next)
#define mem(a,b) memset(a,b,sizeof(a))
#define mec(a,b) memcpy(a,b,sizeof(b))
#define cheak(i) printf("%d ",i)
#define min(a,b) (a>b?b:a)
#define max(a,b) (a>b?a:b)
#define inf 0x7fffffff
typedef long long LL;
#define maxn 10005
struct node
{
    int st,ed,num,t;
}s[maxn];
int A[maxn],tot1;
struct star
{
    int next,to,sta,val,c,f;
}e[maxn*2];
int h[maxn],cur[maxn],gap[maxn],dep[maxn],pre[maxn];
int tot;
void add(int a,int b,int c)
{
    e[++tot].next=h[a];
    e[tot].sta=a;
    e[tot].to=b;
    e[tot].c=c;
    e[tot].f=0;
    h[a]=tot;
}
void start()
{
    mem(h,-1);tot=1;
}
int sap(int st,int ed,int N)
{
    int i,v;
    mem(gap,0);mem(dep,0);
    mec(cur,h);
    int u=st;
    pre[u]=-1;
    gap[0]=N;
    int ans=0;
    while(dep[st]<N)
    {
        //--------------------第一部分 
        if(u==ed)
        {
            int Min=inf;
            for(i=pre[u];i!=-1;i=pre[e[i^1].to])
            if(Min>e[i].c-e[i].f)
            Min=e[i].c-e[i].f;
            for(i=pre[u];i!=-1;i=pre[e[i^1].to])
            {
                e[i].f+=Min;
                e[i^1].f-=Min;
            }
            u=st;
            ans+=Min;
            continue;
        }
        //--------------------end
        //--------------------第二部分 
        bool flag=0;
        sfor(i,u,cur)
        {
            v=e[i].to;
            if(e[i].c-e[i].f&&dep[v]+1==dep[u])
            {
                flag=1;
                cur[u]=pre[v]=i;
                break;
            }
        }
        if(flag)
        {
            u=v;continue;
        }
        //--------------------end
        //--------------------第三部分 
        int Min=N;
        sfor(i,u,h)
        if(e[i].c-e[i].f&&dep[e[i].to]<Min)
        {
            Min=dep[e[i].to];
            cur[u]=i;
        }
        gap[dep[u]]--;
        if(!gap[dep[u]])
        return ans;
        dep[u]=Min+1;
        gap[dep[u]]++;
        if(u!=st) u=e[pre[u]^1].to;
        //--------------------end
    } 
    return ans;
}
int main()
{
    int n,m,i,ans,k,j;
    while(~scanf("%d%d",&n,&m))
    {
        start();
        ans=tot1=0;
        rfor(i,1,n)
        {
            scanf("%d%d%d%d",&s[i].st,&s[i].num,&s[i].ed,&s[i].t);
            A[++tot1]=s[i].ed;
            A[++tot1]=s[i].st;
            ans+=s[i].num*s[i].t;
        }
        sort(A+1,A+tot1+1);
        int k=1;
        rfor(i,2,tot1)
        if(A[i]!=A[i-1]) A[++k]=A[i];
        tot1=k;
        int st=k+n,ed=k+n+1;
        rfor(i,1,k-1)
        add(st,i+n,(A[i+1]-A[i])*m),add(i+n,st,0);
        rfor(i,1,n)
         rfor(j,1,tot1)
         if(A[j]>=s[i].st&&A[j]<s[i].ed)
         {
             add(n+j,i,inf);add(i,n+j,0);
         }
         else if(A[j]>=s[i].ed) break;
        rfor(i,1,n)
        add(i,ed,s[i].num*s[i].t),add(ed,i,0);
        if(ans==sap(st,ed,ed)) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值