URAL 1774 Barber of the Army of Mages 网络流

来源:互联网 发布:linux proc net dev 编辑:程序博客网 时间:2024/06/16 08:34

题目大意:有N个烙饼,一个平底锅最多可以一次放K张饼。一个饼正反面都需要烙,烙一个面至少需要一个单位的时间。第i个饼会第ti时间送到厨房,要是在si时间内还没有烙好,顾客就会投诉。问存不存在一种烙饼方案,使得所有饼都按时烙好。存在则输出Yes,并输出每个饼的下锅时间和出炉时间,不存在则输出No。

这题一乍一看还以为是贪心,遗憾的是WA了。听了题解顿悟是网络流。
建图是这样的,对于每一张饼,与它所有能够被烙的时间点连一条容量为1的边,并与汇点连一条容量为2的边(表示正反面各烙一单位时间),接着从源点向所有单位时间连一条容量为K的边,表示一个时刻锅里最多有K张饼(烙过一次的饼可以暂时离锅)。

(ISAP)

#include <bits/stdc++.h>#define MAXN 3000#define INIT 16843009using namespace std;const int S=2222,T=2333;int f[MAXN][MAXN],gap[MAXN],pre[MAXN],d[MAXN],ct;vector<int>p[MAXN];typedef vector<int>::iterator iter;queue<int>q;void bfs(int s){    memset(d,1,sizeof d);    memset(gap,0,sizeof gap);    d[s]=0;gap[0]=1;    q.push(s);    while(!q.empty()){        int tmp=q.front();q.pop();++ct;        for(iter it=p[tmp].begin();it!=p[tmp].end();it++){            if(f[*it][tmp]>0 && d[*it]==INIT){                d[*it]=d[tmp]+1;                ++gap[d[*it]];                q.push(*it);            }        }    }}int f_next(int x){    for(iter it=p[x].begin();it!=p[x].end();it++)        if(f[x][*it]>0 && d[x]==d[*it]+1)            return *it;    return -1;}int isap(){    bfs(T);    int u=S,ans=0;    memset(pre,-1,sizeof pre);    while(d[u]<ct){        int v=f_next(u);        if(v>=0){            pre[v]=u;u=v;            if(u==T){                int k=INIT;                for(int i=u;i!=S;i=pre[i])                    k=min(k,f[pre[i]][i]);                for(int i=u;i!=S;i=pre[i])                    f[pre[i]][i]-=k,f[i][pre[i]]+=k;                ans+=k;                u=S;            }        }else{            if(--gap[d[u]]==0)return ans;            int mind=T;            for(iter it=p[u].begin();it!=p[u].end();it++)                if(f[u][*it]>0)mind=min(mind,d[*it]+1);            ++gap[mind];            d[u]=mind;            if(u!=S)u=pre[u];        }    }    return ans;}//ISAP void add(int u,int v,int flow){    p[u].push_back(v);    p[v].push_back(u);    f[u][v]=flow;}//加边 int main(){    int n,k;    scanf("%d%d",&n,&k);    for(int i=1,l,r;i<=n;i++){        scanf("%d%d",&l,&r);        r+=l-1;        for(int j=l;j<=r;j++)            add(j,i+2000,1);            //每一张饼与所有能够被烙的时间点连一条容量为1的边        add(i+2000,T,2);        //每一张饼与汇点连一条容量为2的边    }    for(int i=0;i<=2000;i++)add(S,i,k);    //从源点向所有单位时间连一条容量为K的边    int mflow=isap();    if(mflow!=2*n)printf("No\n");    else{        printf("Yes\n");        for(int i=1;i<=n;i++){            int answer[2],cnt=0;            for(iter it=p[i+2000].begin();it!=p[i+2000].end();it++)                if(f[i+2000][*it]==1)answer[cnt++]=*it;            if(answer[0]>answer[1])swap(answer[0],answer[1]);            printf("%d %d\n",answer[0],answer[1]);        }    }    return 0;} 
0 0
原创粉丝点击