[网络流24题] 13. 星际转移问题 解题报告

13.星际转移问题

题意

有 \(n\) 个太空站, \(m\) 艘太空船,

太空船 \(i\) 一次能容下 \(h_i\) 个人,

每艘太空船会按照自己的航线循环行驶, 每行驶一个站点需要一个单位时间,

求从节点 \(0\) 到节点 \(n+1\) 所需的最小时间.

思路

一道一开始完全没有思路的题, 后来发现姆爷又发了新专, 果断地剁手后听了一会, 这道题就想出来了......


总思路是把每个太空站都按时间分为若干个节点,

也就是说, 每加一个单位时间, 我们就把这总共 \(n+2\) 个点全部建一遍 (包括 \(0\) 节点和 \(n+1\) 节点).

对于每艘太空船, 我们都按照它的航线向右建边, 也就是向它下一个单位时刻会到达的节点连边,

除此之外, 每个时刻的每个太空站还要向下一时刻的自己连边, 容量为 \(inf\), 表示在等太空船.


题解的做法是先用并查集判断是否能到达终点, 然后按时间依次加点加边, 在残量网络上跑最大流就行了.

我比较蠢.....先随便选了一个很大的数作为总时间, 然后直接把整张图建出来跑了一个最小费用最大流...


代码

#include<bits/stdc++.h>
using namespace std;
const int _=20+7;
const int __=700+7;
const int ___=3e3+7;
const int inf=0x3f3f3f3f;
int n,m,num,S,T,des,st[_],dis[__],max_flow,ans,limit=30;
int lst[__],nxt[___],to[___],c[___],w[___],tot=1;
bool vis[__];
queue<int> q;
void add(int x,int y,int cap,int wgt){
  //printf("(%d,%d,%d,%d)\n",x,y,cap,wgt);
  nxt[++tot]=lst[x]; to[tot]=y; c[tot]=cap; w[tot]=wgt; lst[x]=tot;
  nxt[++tot]=lst[y]; to[tot]=x; c[tot]=0; w[tot]=-wgt; lst[y]=tot;
}
void init(){
  cin>>n>>m>>num;
  S=(n+2)*(limit+1); T=S+1; des=T+1;
  int h,cy;
  for(int i=1;i<=m;i++){
    scanf("%d%d",&h,&cy);
    for(int j=1;j<=cy;j++){
      scanf("%d",&st[j]);
      if(st[j]==-1) st[j]=n+1;
    }
    int time=0,j=1,t=0;
    while(time<limit){
      int x=st[j],y=st[j==cy ?1 :j+1];
      add(x+t,y+t+n+2,h,1);
      t+=n+2; time++;
      j= j==cy ?1 :j+1;
    }
  }
  for(int t=0;t<limit;t++){
    int tt=t*(n+2);
    for(int i=0;i<=n+1;i++)
      add(i+tt,i+tt+n+2,inf,1);
  }
  add(S,0,num,0);
  add(des,T,num,0);
  for(int i=0;i<=limit;i++)
    add(n+1+i*(n+2),des,inf,0);
}
bool SPFA(){
  for(int i=0;i<=des;i++){ dis[i]=inf; vis[i]=0; }
  while(!q.empty()) q.pop();
  dis[S]=0; q.push(S);
  while(!q.empty()){
    int u=q.front(); q.pop();
    vis[u]=0;
    for(int i=lst[u];i;i=nxt[i]){
      int v=to[i];
      if(!c[i]||dis[v]<=dis[u]+w[i]) continue;
      dis[v]=dis[u]+w[i];
      if(!vis[v]){
    q.push(v);
    vis[v]=1;
      }
    }
  }
  memset(vis,0,sizeof(vis));
  return dis[T]!=inf;
}
int dfs(int u,int flow){
  if(u==T) return flow;
  int rest=flow; vis[u]=1;
  for(int i=lst[u];i;i=nxt[i]){
    int v=to[i];
    if(vis[v]||dis[v]!=dis[u]+w[i]||!c[i]) continue;
    int cst=dfs(v,min(rest,c[i]));
    if(cst==0) dis[v]=inf;
    else{
      c[i]-=cst; c[i^1]+=cst;
      rest-=cst;
    }
  }
  vis[u]=0;
  return flow-rest;
}
void Dinic(){
  int flow;
  while(SPFA())
    do{
      flow=dfs(S,inf);
      max_flow+=flow;
    }while(flow);
  //printf("max_flow: %d\n",max_flow);
}
void print(){
  for(int i=lst[des];i;i=nxt[i])
    if(to[i]!=T&&c[i]&&to[i]>ans) ans=to[i];
  ans=(ans-(n+1))/(n+2);
  printf("%d\n",ans);
}
int main(){
#ifndef ONLINE_JUDGE
  freopen("x.in","r",stdin);
#endif
  init();
  Dinic();
  if(max_flow<num) puts("0");
  else print();
  return 0;
}

原文地址:https://www.cnblogs.com/brucew-07/p/12207372.html

时间: 2024-12-16 02:14:39

[网络流24题] 13. 星际转移问题 解题报告的相关文章

[CTSC1999]【网络流24题】星际转移

Description 由于人类对自然资源的消耗,人们意识到大约在2300 年之后,地球就不能再居住了.于是在月球上建立了新的绿地,以便在需要时移民.令人意想不到的是,2177 年冬由于未知的原因,地球环境发生了连锁崩溃,人类必须在最短的时间内迁往月球.现有n个太空站 位于地球与月球之间,且有m 艘公共交通太空船在其间来回穿梭.每个太空站可容纳无限多的人,而每艘太空船i 只可容纳H[i]个人.每艘太空船将周期性地停靠一系列的太空站,例如:(1,3,4)表示该太空船将周期性地停靠太空站134134

【网络流24题】星际转移问题

Description 由于人类对自然资源的消耗,人们意识到大约在 2300 年之后,地球就不能再居住了.于是在月球上建立了新的绿地,以便在需要时移民.令人意想不到的是,2177 年冬由于未知的原因,地球环境发生了连锁崩溃,人类必须在最短的时间内迁往月球.现有 n 个太空站位于地球与月球之间,且有 m 艘公共交通太空船在其间来回穿梭.每个太空站可容纳无限多的人,而每艘太空船 i 只可容纳 H[i]个人.每艘太空船将周期性地停靠一系列的太空站,例如:(1,3,4)表示该太空船将周期性地停靠太空站

线性规划与网络流24题●09方格取数问题&amp;13星际转移问题

●(做codevs1908时,发现测试数据也涵盖了1907,想要一并做了,但因为"技术"不佳,搞了一上午) ●09方格取数问题(codevs1907  方格取数3) 想了半天,也没成功建好图: 无奈下参考题解,说是本题要求二分图点权最大独立集,然后可以由结论:"最大点权独立集 = 所有点权 - 最小点权覆盖集 = 所有点权 - 最小割集 = 所有点权 - 网络最大流"转化到求最大流(我真的很懵逼,但又感觉很有道理): 下面附上solution:(自己领悟吧) (不懂

[CTSC1999][网络流24题] 星际转移

36. [CTSC1999][网络流24题] 星际转移 ★★★☆   输入文件:home.in   输出文件:home.out   简单对比时间限制:1 s   内存限制:128 MB «问题描述: 由于人类对自然资源的消耗,人们意识到大约在2300 年之后,地球就不能再居住了. 于是在月球上建立了新的绿地,以便在需要时移民.令人意想不到的是,2177 年冬由于未 知的原因,地球环境发生了连锁崩溃,人类必须在最短的时间内迁往月球.现有n个太空站 位于地球与月球之间,且有m 艘公共交通太空船在其间

【网络流24题】 No.12 软件补丁问题(最小转移代价 最短路)

[题意] T 公司发现其研制的一个软件中有 n 个错误, 随即为该软件发放了一批共 m 个补丁程序. 每一个补丁程序都有其特定的适用环境, 某个补丁只有在软件中包含某些错误而同时又不包含另一些错误时才可以使用.一个补丁在排除某些错误的同时, 往往会加入另一些错误.换句话说, 对于每一个补丁 i, 都有 2 个与之相应的错误集合 B1[i]和 B2[i],使得仅当软件包含 B1[i]中的所有错误, 而不包含 B2[i]中的任何错误时, 才可以使用补丁 i. 补丁 i 将修复软件中的某些错误 F1[

「网络流24题」 题目列表

「网络流24题」 题目列表 序号 题目标题 模型 题解 1 飞行员配对方案问题 二分图最大匹配 <1> 2 太空飞行计划问题 最大权闭合子图 <2> 3 最小路径覆盖问题 二分图最小路径覆盖 <3> 4 魔术球问题 <4> 5 圆桌问题 <5> 6 最长递增子序列问题 <6> 7 试题库问题 <7> 8 机器人路径规划问题 <8> 9 方格取数问题 二分图最大点权独立集 <9> 10 餐巾计划问题

【网络流24题----14】孤岛营救问题

孤岛营救问题 Time Limit: 1 Sec  Memory Limit: 128 MB Description 1944年,特种兵麦克接到国防部的命令.要求马上赶赴太平洋上的一个孤岛,营救被敌军俘虏的大兵瑞恩.瑞恩被关押在一个迷宫里,迷宫地形复杂,但幸好麦克得到了迷宫的地形图.迷宫的外形是一个长方形,其南北方向被划分为 N行,东西方向被划分为 M列,于是整个迷宫被划分为 N×M个单元.每个单元的位置可用一个有序数对 (单元的行号,单元的列号)来表示.南北或东西方向相邻的 2个单元之间可能互

【线性规划与网络流24题】孤岛营救问题 分层图

孤岛营救问题 Time Limit: 1 Sec  Memory Limit: 128 MB Description 1944年,特种兵麦克接到国防部的命令,要求立即赶赴太平洋上的一个孤岛,营救被敌军俘虏的大兵瑞恩.瑞恩被关押在一个迷宫里,迷宫地形复杂,但幸好麦克得到了迷宫的地形图.迷宫的外形是一个长方形,其南北方向被划分为 N行,东西方向被划分为 M列,于是整个迷宫被划分为 N×M个单元.每一个单元的位置可用一个有序数对 (单元的行号,单元的列号)来表示.南北或东西方向相邻的 2个单元之间可能

网络流24题小结

网络流24题 前言 网络流的实战应用篇太难做了,因此先完善这一部分 ## 第一题:飞行员配对方案 \(BSOJ2542\)--二分图 最优匹配 题意 两国飞行员\(x\)集合\(y\)集合,\(x\)飞行员可以配对特定的\(y\)集合的飞行员(可无),求一对一配对最大数 Solution 二分图最大匹配裸题,最大流实现 建图:(设\(i\in x\)而\(i'\in y\)) \((S,i,1)~(i',T,1)\) 对\((i,j')\)可匹配\((i,j',1)\) Code 略 ## 第二