1. 程式人生 > >【網絡流24題】星際轉移問題

【網絡流24題】星際轉移問題

out n+1 rip scanf 網絡流24題 時間 names body pop

Description

由於人類對自然資源的消耗,人們意識到大約在 2300 年之後,地球就不能再居住了。於是在月球上建立了新的綠地,以便在需要時移民。令人意想不到的是,2177 年冬由於未知的原因,地球環境發生了連鎖崩潰,人類必須在最短的時間內遷往月球。現有 n 個太空站位於地球與月球之間,且有 m 艘公共交通太空船在其間來回穿梭。每個太空站可容納無限多的人,而每艘太空船 i 只可容納 H[i]個人。每艘太空船將周期性地停靠一系列的太空站,例如:(1,3,4)表示該太空船將周期性地停靠太空站 134134134…。每一艘太空船從一個太空站駛往任一太空站耗時均為 1。人們只能在太空船停靠太空站(或月球、地球)時上、下船。初始時所有人全在地球上,太空船全在初始站。試設計一個算法,找出讓所有人盡快地全部轉移到月球上的運輸方案。

對於給定的太空船的信息,找到讓所有人盡快地全部轉移到月球上的運輸方案。

Solution

建立時間分層圖,即把每一個點再每一個時間都對應到一個點上
然後枚舉時間加點加邊
設地球為\(n+1\),月球為\(n+2\)
\((S,n+1,inf),(T,n+1,inf)\)
\((i,i',inf)\) 即每一個時間向下一個時間相對應的點連邊,相當於在某個點停留
\((x,y',h[i])\) 枚舉每一艘太空船在這一個時間的航線\((x,y)\),對應連邊
直到最大流大於等於\(k\),當前時間就是答案

#include<bits/stdc++.h>
using namespace
std; const int N=1005,M=100005,inf=2e8; int head[N],nxt[M],to[M],num=1,dis[M],n,m,K; void link(int x,int y,int z){ nxt[++num]=head[x];to[num]=y;head[x]=num;dis[num]=z; nxt[++num]=head[y];to[num]=x;head[y]=num;dis[num]=0; } int c[N],a[N][N],h[N],dep[N],S,T;queue<int>q; inline bool bfs(){ memset(dep,0
,sizeof(dep)); q.push(S);dep[S]=1; while(!q.empty()){ int x=q.front();q.pop(); for(int i=head[x];i;i=nxt[i]){ int u=to[i]; if(dep[u] || dis[i]<=0)continue; dep[u]=dep[x]+1;q.push(u); } } return dep[T]; } inline int dfs(int x,int flow){ if(x==T || !flow)return flow; int u,tot=0,t; for(int i=head[x];i;i=nxt[i]){ u=to[i]; if(dep[u]!=dep[x]+1 || dis[i]<=0)continue; t=dfs(u,min(flow,dis[i])); dis[i]-=t;dis[i^1]+=t; flow-=t;tot+=t; if(!flow)break; } if(!tot)dep[x]=-1; return tot; } inline int Dinic(){ int tot=0,t; while(bfs()){ t=dfs(S,inf); while(t)tot+=t,t=dfs(S,inf); } return tot; } int main(){ freopen("pp.in","r",stdin); freopen("pp.out","w",stdout); scanf("%d%d%d",&n,&m,&K);T=N-1; for(int i=1;i<=m;i++){ scanf("%d%d",&h[i],&c[i]); for(int j=1;j<=c[i];j++){ scanf("%d",&a[i][j]); if(a[i][j]==-1)a[i][j]=n+2; if(a[i][j]==0) a[i][j]=n+1; } } n+=2; link(S,n-1,inf);link(n,T,inf); int x,y,t=0; for(int o=1;o<=50;o++){ for(int i=1;i<=n;i++)link((o-1)*n+i,o*n+i,inf); link(S,o*n+n-1,inf);link(o*n+n,T,inf); for(int i=1;i<=m;i++){ x=o%c[i];if(!x)x=c[i]; y=o%c[i]+1; link((o-1)*n+a[i][x],o*n+a[i][y],h[i]); } t+=Dinic(); if(t>=K)printf("%d\n",o),exit(0); } puts("0"); return 0; }

【網絡流24題】星際轉移問題