[聯合集訓6-19] 新幹線 猜測題意+拆點網路流
阿新 • • 發佈:2019-01-22
題意還有一些細節如下:
1. 同一站點同一軌道同一時刻最多隻能發一列貨車
2. 直接經過的列車不佔用停車位
3. 每條軌道上不允許發生客車超過貨車的情況,但同時出發或同時到達某站是合法的,而且不佔用該站臺的停車位,就算客車貨車速度相同且同時出發仍然算合法的
4. 求能發出貨車且在內到達終點的最大值。
題中說到不能影響客車執行,也就是每列客車中途不停,到每個站的時間(同樣也是從該站發車的時間)都是確定的。假設有一列客車在時刻從站出發,那麼可以轉化成一條限制,即這段時間內佔用一條軌道(這段時間內不能向該軌道發貨車),於是我們可以預處理出 表示站在時間可用的軌道數。於是我們把每個站拆成個點,對於向連容量為的邊,向連容量為的邊,跑最大流就是答案。
程式碼:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define G(x,t) ((x)*(mxt+1)+(t))
#define N 60
#define M 210
using namespace std;
const int mxt=200;
const int inf=0x3f3f3f3f;
int tote,n,P[N],T[N],Q[N],S[N],fre[N][M],ans,con[N*M],nxt[N*M<<2],to[N*M<<2],f[N*M<<2],c[N*M<<2],ne[N*M],dl[N*M],ss,tt;
void ins(int x,int y,int cc)
{
to[++tote]=y;c[tote]=cc;nxt[tote]=con[x];con[x]=tote;
to[++tote]=x ;c[tote]=0;nxt[tote]=con[y];con[y]=tote;
}
bool bfs()
{
memset(ne,0,sizeof(ne));
ne[ss]=1;dl[1]=ss;
for(int hd=1,tl=1,v=ss;hd<=tl;v=dl[++hd])
for(int p=con[v];p;p=nxt[p])
if(c[p]>f[p]&&!ne[to[p]])
ne[to[p]]=ne[v]+1,dl[++tl]=to[p];
return ne[tt]>0;
}
int dinic(int v,int flow)
{
if(v==tt) return flow;
if(ne[v]==-1) return 0;
int re=0;
for(int p=con[v];p&&flow;p=nxt[p])
if(c[p]>f[p]&&ne[to[p]]==ne[v]+1)
{
int o=dinic(to[p],min(flow,c[p]-f[p]));
f[p]+=o;f[p^1]-=o;
re+=o;flow-=o;
}
if(!re) ne[v]=-1;
return re;
}
int main()
{
scanf("%d",&n);
for(int i=0;i<=n;i++)
scanf("%d",&P[i]);
for(int i=0;i<=n;i++)
scanf("%d",&T[i]);
for(int i=0;i<=n;i++)
scanf("%d",&Q[i]);
for(int i=0;i<=n;i++)
scanf("%d",&S[i]);
for(int i=0;i<=n;i++)
for(int j=0;j<=200;j++)
fre[i][j]=T[i];
while(1)
{
int t,x;
scanf("%d%d",&t,&x);
if(t==-1&&x==-1) break;
for(int i=x;i<=n;t+=Q[i],i++)
for(int j=max(t+Q[i]-S[i]+1,0);j<t;j++)
fre[i][j]--;
}
ss=(n+1)*(mxt+1)+1,tt=(n+1)*(mxt+1)+2;
for(int j=0;j<=mxt;j++)
ins(ss,G(0,j),inf);
for(int i=0;i<=n;i++)
{
for(int j=0;j<=mxt-S[i];j++)
ins(G(i,j),i==n?tt:G(i+1,j+S[i]),fre[i][j]);
for(int j=0;j<mxt;j++)
ins(G(i,j),G(i,j+1),P[i]);
}
while(bfs()) ans+=dinic(ss,inf);//puts("!!!!");
printf("%d",ans);
return 0;
}