接下来的 m 行给出太空船的信息。第 i+1 行说明太空船 pi。第 1 个数表示 pi 可容纳的人数 H[pi];第 2 个数表示 pi 一个周期停靠的太空站个数 r;随后 r 个数是停靠的太空站的编号 (Si1,Si2,…,Sir),地球用 0 表示,月球用 −1 表示。
时刻 0 时,所有太空船都在初始站,然后开始运行。
在时刻 1,2,3… 等正点时刻各艘太空船停靠相应的太空站。
人只有在 0,1,2… 等正点时刻才能上下太空船。
输出格式
输出让所有人尽快地全部转移到月球上的最短用时。
如果无解,则输出 0。
数据范围
1≤n≤13, 1≤m≤20, 1≤k≤50, 1≤r≤n+2,
输入样例:
2 211 30121 312 -1
输出样例:
5
解题思路
最大流,网络流24题,分层图
本题考虑建立分层图,即对于 day 天,对于 day 中的每一天针对每个空间站(包括地球和月球)建立一个节点,建立一个源点 S 和汇点 T,S 连向第 0 天的地球代表的节点,且容量为地球人数,这 day 天中月球所代表的节点连向 T,且容量足够大,对于第 day−1 和 day 天节点的关系:每个空间站表示的节点向下一天该空间站表示节点连边,且容量足够大,每个空间船表示一条边,即对于每个空间船来说当天空间站所表示的节点连向下一天空间站表示的节点,且容量为飞船容量,这样从小到大遍历 day,当最大流满流时即找到最小的 day。为什么?当满流时,对应地球表示的节点上的流量都流走了,且最终都经过月球表示的节点,表示实际中地球上的所有人都到了月球,流网络从某天的节点到同一天的节点表示该处的流量不变,即该空间站上的人下一天仍在该空间站,当流向其他空间站表示的节点时,即下一天一定数量的人走到另外一个空间站,流网络可行流对应实际问题
设答案为 k,则:
时间复杂度:O(kn2m)
代码
// Problem: 星际转移问题// Contest: AcWing// URL: https://www.acwing.com/problem/content/2189/// Memory Limit: 64 MB// Time Limit: 1000 ms// // Powered by CP Editor (https://cpeditor.org)// %%%Skyqwq#include<bits/stdc++.h>//#define int long long#define help {cin.tie(NULL); cout.tie(NULL);}#define pb push_back#define fi first#define se second#define mkp make_pairusingnamespace std;
typedeflonglong LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> boolchkMax(T &x, T y){ return (y > x) ? x = y, 1 : 0; }
template <typename T> boolchkMin(T &x, T y){ return (y < x) ? x = y, 1 : 0; }
template <typename T> voidinlineread(T &x){
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
constint N=15*22*55*15,M=(N+15*22*55*15)*2,inf=1e9;
int n,m,k,S,T;
int h[N],f[M],e[M],ne[M],idx;
int fa[25];
int hh,tt,q[N],cur[N],d[N];
structShip{
int h,p;
int s[25];
}ship[30];
voidadd(int a,int b,int c){
e[idx]=b,f[idx]=c,ne[idx]=h[a],h[a]=idx++;
e[idx]=a,f[idx]=0,ne[idx]=h[b],h[b]=idx++;
}
intfind(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
intget(int day,int i){
return day*(n+2)+i;
}
boolbfs(){
memset(d,-1,sizeof d);
hh=tt=d[S]=0;
q[0]=S;
cur[S]=h[S];
while(hh<=tt)
{
int x=q[hh++];
for(int i=h[x];~i;i=ne[i])
{
int y=e[i];
if(d[y]==-1&&f[i])
{
d[y]=d[x]+1;
cur[y]=h[y];
if(y==T)returntrue;
q[++tt]=y;
}
}
}
returnfalse;
}
intdfs(int x,int limit){
if(x==T)return limit;
int flow=0;
for(int i=cur[x];~i&&flow<limit;i=ne[i])
{
cur[x]=i;
int y=e[i];
if(d[y]==d[x]+1&&f[i])
{
int t=dfs(y,min(f[i],limit-flow));
if(!t)d[y]=-1;
f[i]-=t,f[i^1]+=t,flow+=t;
}
}
return flow;
}
intdinic(){
int res=0,flow;
while(bfs())while(flow=dfs(S,inf))res+=flow;
return res;
}
intmain(){
memset(h,-1,sizeof h);
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<25;i++)fa[i]=i;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&ship[i].h,&ship[i].p);
for(int j=0;j<ship[i].p;j++)
{
scanf("%d",&ship[i].s[j]);
if(ship[i].s[j]==-1)ship[i].s[j]=n+1;
if(j)fa[find(ship[i].s[j-1])]=find(ship[i].s[j]);
}
}
if(find(0)!=find(n+1))puts("0");
else {
S=N-1,T=N-2;
int day=0,res=0;
add(S,get(0,0),k);
add(get(0,n+1),T,inf);
while(true)
{
day++;
add(get(day,n+1),T,inf);
for(int i=0;i<=n+1;i++)
{
int x=get(day-1,i),y=get(day,i);
add(x,y,inf);
}
for(int i=1;i<=m;i++)
{
int p=ship[i].p;
int x=get(day-1,ship[i].s[(day-1)%p]);
int y=get(day,ship[i].s[day%p]);
add(x,y,ship[i].h);
}
res+=dinic();
if(res==k)break;
}
printf("%d",day);
}
return0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2021-11-26 匈牙利算法
2021-11-26 染色法判定二分图