HDU2883 kebab(中等) [最大流]判断满流(数据离散化)

来源:互联网 发布:藏刀不能在淘宝卖 编辑:程序博客网 时间:2024/05/01 14:29

题意:有一个烧烤机,每次最多能烤 m 块肉,现在有 n 个人来买烤肉,每个人到达时间为 si,离开时间为 ei,点的烤肉数量为 ci,点的烤肉所需烘烤时间为 di,每个人要烤的肉可以分成若干份在同时烤,问是否存在一种方案可以满足所有顾客的需求。
思路:建图很巧妙,参考网上思路,HDU3572 与本题有些相似之处,但是本题的变化在于,时间的区间跨度太大,不能够与区间的每一个时刻连边,但是注意到人的个数只有200,所以,转换思路,把区间看做点,而不是拆开。直接把所有人的是si,ei,存在一个数组里排序,然后去重(假设去重后的点为num个),那么会剩下num-1个区间,如果某个人的原始区间包含这num-1个区间的某个区间的话,那么他们之间就可以连一条inf的边。源点与n个人连边(边权是(这个人的ci*di))。汇点与时间区间连边(边权是m*(时间的跨度))。

#include<cstdio>#include<algorithm>#include<cmath>#include<queue>#include<cstring>#include<string>using namespace std;#define pb push_back#define cl(a,b) memset(a,b,sizeof(a))const int maxn=205;#define inf 1<<30template<int nv,int ne>struct isap{    int n,size;    int head[nv];    int dis[nv],gap[nv],cur[nv],pre[nv];    int maxflow;    struct edge{        int v,w,next;        edge(){}        edge(int _v,int _w,int _next):v(_v),w(_w),next(_next){}    }E[ne];    void init(int n){        this->n=n,size=0;        cl(head,-1);    }    void insert(int u,int v,int w){        E[size]=edge(v,w,head[u]);        head[u]=size++;        E[size]=edge(u,0,head[v]);        head[v]=size++;    }    int maxFlow(int src,int des){        maxflow=0;        for(int i=0;i<=n;i++){            dis[i]=gap[i]=0;            cur[i]=head[i];        }        int u=pre[src]=src;        int aug=0;///or aug=-1        while(dis[src]<n){           loop:for(int &i=cur[u];i!=-1;i=E[i].next){                int v=E[i].v;                if(E[i].w&&dis[u]==dis[v]+1){                    aug=min(aug,E[i].w);                    pre[v]=u;                    u=v;                    if(v==des){                        maxflow+=aug;                        for(u=pre[u];v!=src;v=u,u=pre[u]){                            E[cur[u]].w-=aug;                            E[cur[u]^1].w+=aug;                        }                        aug=inf;                    }                    goto loop;                }            }            int mdis=n;            for(int i=head[u];i!=-1;i=E[i].next){                int v=E[i].v;                if(E[i].w&&mdis>dis[v]){                    cur[u]=i;                    mdis=dis[v];                }            }            if(--gap[dis[u]]==0)break;            gap[dis[u]=mdis+1]++;            u=pre[u];        }        return maxflow;    }};isap<50005,5001005> G;int s[maxn],e[maxn];int nn[maxn],tt[maxn];int a[4444444];int main(){    int n,m;    while(~scanf("%d%d",&n,&m)){        int sum=0,cnt=0;        for(int i=0;i<n;i++){            scanf("%d%d%d%d",&s[i],&nn[i],&e[i],&tt[i]);            sum+=nn[i]*tt[i];            a[cnt++]=s[i];            a[cnt++]=e[i];        }        sort(a,a+cnt);        int num=0;        for(int i=1;i<cnt;i++){//去掉重复的元素            if(a[num]!=a[i]){                a[++num]=a[i];            }        }        G.init(n+num+2);        for(int i=0;i<n;i++){            G.insert(0,i+1,nn[i]*tt[i]);//源点与人连边        }        for(int i=1;i<=num;i++){            G.insert(n+i,n+num+2,m*(a[i]-a[i-1]));//汇点与时间区间连边            for(int j=0;j<n;j++){                if(s[j]<=a[i-1]&&e[j]>=a[i]){//区间包含,连边                    G.insert(j+1,i+n,inf);                }            }        }        printf("%s\n",(sum==G.maxFlow(0,n+num+2))?"Yes":"No");    }    return 0;}
0 0
原创粉丝点击