您的位置:首页 > 理论基础 > 计算机网络

URAL 1774 Barber of the Army of Mages 网络流

2015-08-27 23:08 363 查看

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

这题一乍一看还以为是贪心,遗憾的是WA了。听了题解顿悟是网络流。

建图是这样的,对于每一张饼,与它所有能够被烙的时间点连一条容量为1的边,并与汇点连一条容量为2的边(表示正反面各烙一单位时间),接着从源点向所有单位时间连一条容量为K的边,表示一个时刻锅里最多有K张饼(烙过一次的饼可以暂时离锅)。

(ISAP)

#include <bits/stdc++.h>
#define MAXN 3000
#define INIT 16843009
using 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  网络流 URAL-1774