zoukankan      html  css  js  c++  java
  • 【最大流】【HDU2883】【kebab】

    题意: 有一个烧烤机,每次最多能烤 m 块肉,现在有 n 个人来买烤肉,每个人到达时间为 si,离开时间为 ei,点的烤肉数量为 ci,点的烤肉所需烘烤时间为 di,

              每个人要烤的肉可以分成若干份在同时烤,问是否存在一种方案可以满足所有顾客的需求。

    分析: 将所有的到达时间和结束时间按升序排序,得到 x <= 2n-1 个时间区间。


              建图:

              s为源,t为汇,

              每个顾客i作为一个结点并连边(s, i, ni*ti)

              每个区间j作为一个结点并连边(j, t, (ej-sj)*M),其中sj, ej分别表示区间j的起始时间和终止时间

              对任意顾客i和区间j,若 [sj, ej] 完全包含在 [si, ei] 之中,则连边(i, j, INF)

              若最大流等于 ∑ni*ti 则是 Yes,否则是 No。


    如果si,ei 的值小于200 ,可以直接以时间点建边,而非区间,类似题目见HDU3572.


    代码:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <climits>
    #include <algorithm>
    using namespace std;
    #define min(a,b)(a)<(b)?(a):(b)
    const int INF=INT_MAX;
    const int maxn=2000;
    const int maxm=10000000;
    struct node
    {
        int from,to,next,c;
    }e[maxm];
    int tot;
    int head[maxn];
    void add(int s,int u,int f1,int f2)
    {
        e[tot].from=s;
        e[tot].to=u;
        e[tot].c=f1;
        e[tot].next=head[s];
        head[s]=tot++;
        e[tot].from=u;
        e[tot].to=s;
        e[tot].c=f2;
        e[tot].next=head[u];
        head[u]=tot++;
    }
    int q[maxn];
    int cnt[maxn];
    int d[maxn];
    int low[maxn];
    int cur[maxn];
    int maxflow(int s,int t,int n)
    {
        int *front=q,*rear=q;
        for(int i=0;i<n;i++)
        {
            d[i]=n;
            cnt[i]=0;
        }
        cnt[n]=n-1;
        cnt[0]++;
        d[t]=0;
        *rear++=t;
        while(front<rear)
        {
            int v=*front++;
            for(int i=head[v];i!=-1;i=e[i].next)
            {
                if(d[e[i].to]==n&&e[i^1].c>0)
                {
                    d[e[i].to]=d[v]+1;
                    cnt[n]--;
                    cnt[d[e[i].to]]++;
                    *rear++=e[i].to;
                }
            }
        }
        int flow=0, u=s, top=0;
        low[0]=INF;
        for(int i=0;i<n;i++)
            cur[i]=head[i];
        while(d[s]<n)
        {
            int &i=cur[u];
            for(;i!=-1;i=e[i].next)
            {
                if(e[i].c>0&&d[u]==d[e[i].to]+1)
                {
                    low[top+1]=min(low[top],e[i].c);
                    q[++top]=i;
                    u=e[i].to;
                    break;
                }
            }
            if(i!=-1)
            {
                if(u==t)
                {
                    int minf=low[top];
                    for(int p=1,i;p<=top;++p)
                    {
                        i=q[p];
                        e[i].c-=minf;
                        e[i^1].c+=minf;
                    }
                    flow+=minf;
                    u=s;
                    low[0]=INF;
                    top=0;
                }
            }
            else
            {
                int old_du=d[u];
                cnt[old_du]--;
                d[u]=n-1;
                for(int i=head[u];i!=-1;i=e[i].next)
                    if(e[i].c>0&&d[u]>d[e[i].to])
                        d[u]=d[e[i].to];
                cnt[++d[u]]++;
                if(d[u]<n)
                    cur[u]=head[u];
                if(u!=s)
                {
                    u=e[q[top]].from;
                    --top;
                }
                if(cnt[old_du]==0)
                    break;
            }
        }
        return flow;
    }
    struct edge
    {
        int st,en,c,d;
    }ta[205];
    int di[500];
    int main()
    {
        int i, j, k, n, m;
        int sum;
        while(scanf("%d %d",&m, &n)!=EOF)
        {
            tot = 0;
            sum = 0;
            memset(head,-1,sizeof(head));
            int s = 0;
            int t = m+2*m;
            int a,b,c,d;
            int top = 0;
            for(i = 1; i <= m; i++)
            {
                scanf("%d %d %d %d",&ta[i].st, &ta[i].c, &ta[i].en, &ta[i].d);
                di[top++] = ta[i].st;
                di[top++] = ta[i].en;
            }
            sort(di,di+top);
            top--;
            for(i = 1; i <= top; i++)
                add(i+m,t,(di[i]-di[i-1])*n,0);
            for(i = 1; i <= m; i++)
            {
                add(s,i,ta[i].c*ta[i].d,0);
                sum += ta[i].c*ta[i].d;
                for(j = 1; j <= top; j++)
                    if(ta[i].st<=di[j-1]&&di[j] <=ta[i].en)
                          add(i,j+m,INF,0);
            }
            int res = maxflow(s,t,t+1);
            if(res == sum)
            printf("Yes
    ");
            else printf("No
    ");
        }
        return 0;
    }


  • 相关阅读:
    微信小程序支付服务商版-发起支付
    count(1),count(*),count(主键) 性能对比
    SpringBoot_yml配置文件
    Java字符串加密,UUID+MD5进行加密
    WebSocket实现C#端和H5进行交互
    SpringBoot配置文件详解
    SQL中的limit
    SQL中的union简述
    数据库中的子查询
    数据库中的连接查询
  • 原文地址:https://www.cnblogs.com/zy691357966/p/5480349.html
Copyright © 2011-2022 走看看