题目大意:地球与月球间有可容纳无限人的太空站,还有在太空站与星球间按周期行驶的、有固定容量的太空船,每一艘太空船从一个太空站驶往任一太空站耗时均为 1。地球上有一定数量的人,问所有人到月球最少需要多少天。

关键词:分层 最小费用最大流

最大流:把人群看作流。

分层:人们的最优选择会受到其位于哪一天的影响,因此我们关于时间将整个图分层。估计一下最多能用多少天,就分多少层。人们在太空站内可以呆着,因此每天的太空站要向下一天的太空站连容量∞费用1边。太空船运人,因此太空船前一站向下一天的后一站连容量∞费用1边。人类量固定,从S点向第一天的地球连容量为人数费用0边。任意时刻到达月球均可,从每天的月球向T连容量为无穷费用0边。

最小费用:这里的MCMF有些不同:费用不是单位费用,而是绝对费用;最小费用是每次SPFA所得路径的总费用的最大值,而不是和(否则同一天两群人坐船就被算成了两天)。

#include <cstdio>
#include <cstring>
#include <cassert>
#include <queue>
#include <vector>
using namespace std;
//#define test #define LOOP(i,n) for(int i=1; i<=n; i++)
#define S(station, day) station + (day - 1) * TotStation
#define R(x, t) (x - 1) % (t) + 1
#define INF 0x3f3f3f3f
const int MAX_SHIP = , MAX_STOP = , MAX_DAY = , MAX_NODE = MAX_STOP * MAX_DAY; int TotStation, TotShip, TotHuman;
int Cap[MAX_SHIP], Route[MAX_SHIP][MAX_STOP], StopCnt[MAX_STOP]; struct MCMF
{
struct Node;
struct Edge; struct Node
{
Edge *Head, *Prev;
int Dist, Id;
bool Inq;
}; struct Edge
{
int Cap, Cost, OrgCap;
Node *From, *To;
Edge *Next, *Rev;
}; Node _nodes[MAX_NODE];
vector<Edge*> _edges;
int _vCount = , _eCount = ;
Node *Start, *Sink;
int TotFlow, TotCost; void Init(int n, int sId, int tId)
{
_vCount = n;
_eCount = ;
Start = &_nodes[sId], Sink = &_nodes[tId];
TotFlow = TotCost = ;
} Edge *NewEdge()
{
if (_eCount < _edges.size())
return _edges[_eCount];
else
{
_edges.push_back(new Edge());
return _edges[_eCount++];
}
} Edge* AddEdge(Node *from, Node *to, int cap, int cost)
{
Edge *e = NewEdge();
e->From = from;
e->To = to;
e->OrgCap = e->Cap = cap;
e->Cost = cost;
e->Next = e->From->Head;
e->From->Head = e;
return e;
} void Build(int uId, int vId, int cap, int cost)
{
Node *u = uId + _nodes, *v = vId + _nodes;
u->Id = uId;
v->Id = vId;
Edge *edge1 = AddEdge(u, v, cap, cost), *edge2 = AddEdge(v, u, , -cost);
edge1->Rev = edge2;
edge2->Rev = edge1;
} bool SPFA()
{
queue<Node*> q;
LOOP(i, _vCount)
{
_nodes[i].Prev = NULL;
_nodes[i].Dist = INF;
_nodes[i].Inq = false;
}
Start->Dist = ;
q.push(Start);
while (!q.empty())
{
Node *u = q.front();
q.pop();
//printf("SPFA %d Dist %d\n", u->Id, u->Dist);
u->Inq = false;
for (Edge *e = u->Head; e; e = e->Next)
{
if (e->Cap && u->Dist + e->Cost < e->To->Dist)
{
e->To->Dist = u->Dist + e->Cost;
e->To->Prev = e;
if (!e->To->Inq)
{
e->To->Inq = true;
q.push(e->To);
}
}
}
}
return Sink->Prev;
} void Proceed()
{
while (SPFA())
{
assert(Sink->Dist != INF);
int minFlow = INF, curCost = ;
for (Edge *e = Sink->Prev; e; e = e->From->Prev)
minFlow = min(minFlow, e->Cap);
TotFlow += minFlow;
for (Edge *e = Sink->Prev; e; e = e->From->Prev)
{
e->Cap -= minFlow;
e->Rev->Cap += minFlow;
curCost += e->Cost;
}
TotCost = max(TotCost, curCost);
}
}
}g; int Proceed(int totDay)
{
int sId = TotStation*totDay + , tId = TotStation*totDay + ;
g.Init(tId, sId, tId);
g.Build(sId, , TotHuman, );
for (int i = ; i < sId; i += TotStation)
g.Build(i, tId, INF, );
LOOP(station, TotStation)
LOOP(day, totDay - )
g.Build(S(station, day), S(station, day + ), INF, );
LOOP(ship, TotShip)
LOOP(day, totDay - )
g.Build(S(Route[ship][R(day, StopCnt[ship])], day), S(Route[ship][R(day + , StopCnt[ship])], day + ), Cap[ship], );
g.Proceed();
if (g.TotFlow < TotHuman)
return ;
return g.TotCost;
} int main()
{
#ifdef _DEBUG
freopen("c:\\noi\\source\\input.txt", "r", stdin);
#endif
scanf("%d%d%d", &TotStation, &TotShip, &TotHuman);
TotStation += ;
LOOP(i, TotShip)
{
scanf("%d%d", i + Cap, i + StopCnt);
LOOP(j, StopCnt[i])
{
scanf("%d", &Route[i][j]);
Route[i][j] += ;
}
}
printf("%d\n", Proceed(MAX_DAY));
return ;
}

注意:

1.要让包括星球在内的太空站的编号从1开始,否则容易晕。

2.最大值不要卡着边设。

luogu2754 星际转移问题 网络流的更多相关文章

  1. luogu2754 星际转移问题

    源向地球连 月球向汇连 每一天往下一天连 飞船上一天与这一天连 枚举答案 #include <iostream> #include <cstring> #include < ...

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

    36. [CTSC1999][网络流24题] 星际转移 ★★★☆   输入文件:home.in   输出文件:home.out   简单对比时间限制:1 s   内存限制:128 MB «问题描述: ...

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

    ●(做codevs1908时,发现测试数据也涵盖了1907,想要一并做了,但因为“技术”不佳,搞了一上午) ●09方格取数问题(codevs1907  方格取数3) 想了半天,也没成功建好图: 无奈下 ...

  4. 【BZOJ3993】星际战争(网络流,二分答案)

    [BZOJ3993]星际战争(网络流,二分答案) 题面 Description 3333年,在银河系的某星球上,X军团和Y军团正在激烈地作战.在战斗的某一阶段,Y军团一共派遣了N个巨型机器人进攻X军团 ...

  5. Luogu 2469 [SDOI2010]星际竞速 / HYSBZ 1927 [Sdoi2010]星际竞速 (网络流,最小费用流)

    Luogu 2469 [SDOI2010]星际竞速 / HYSBZ 1927 [Sdoi2010]星际竞速 (网络流,最小费用流) Description 10年一度的银河系赛车大赛又要开始了.作为全 ...

  6. Luogu P2754 星际转移问题

    Luogu P2754 星际转移问题 思路 首先,对于地球能否到达月球的问题,考虑使用并查集维护. 对于每艘飞船能够到达的站点,放进一个集合里,若两艘飞船的集合有交集,那么就合并两个集合,最后只要地球 ...

  7. 网络流24题之星际转移问题(洛谷P2754)

    洛谷 P2754 题目背景 none! 题目描述 由于人类对自然资源的消耗,人们意识到大约在 2300 年之后,地球就不能再居住了.于是在月球上建立了新的绿地,以便在需要时移民.令人意想不到的是,21 ...

  8. 【网络流24题】No. 13 星际转移问题 (网络判定 最大流)

    [题意] 由于人类对自然资源的消耗, 人们意识到大约在 2300 年之后, 地球就不能再居住了.于是在月球上建立了新的绿地,以便在需要时移民. 令人意想不到的是, 2177 年冬由于未知的原因, 地球 ...

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

    Description 由于人类对自然资源的消耗,人们意识到大约在2300 年之后,地球就不能再居住了.于是在月球上建立了新的绿地,以便在需要时移民.令人意想不到的是,2177 年冬由于未知的原因,地 ...

随机推荐

  1. 遍历WPF DataGrid单元格

    using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Media; ...

  2. PHP 框架Laravel Eloquent 实现身份验证

    PHP自从5.3后似乎又热度又回升, 最近了解了一下PHP框架之一Laravel, 最近最新的版本已经是4.3  基本的结构这里不讲, 要了解可以在这里看文档 http://v4.golaravel. ...

  3. 搭建Hive所遇到的坑

    ##一.基本功能: 1.启动hive时报错 java.lang.ExceptionInInitializerError at java.lang.Class.forName0(Native Metho ...

  4. 【Linux】ubuntu中怪异的vi编辑器

    由于前几天一场windows系统的比特币勒索病毒,我下狠心装了Linux的ubuntu版本.可是今天在使用命令行中的vi编辑器时出现了怪异的现象:backspace不能删除,编辑模式回车随机出现字母. ...

  5. PyCharm for Mac 调整字体大小

    网上的教程大多已过时,那个路径根本找不到,于是就有了本文. 前言 以前用 Sublime 时,直接快捷键CMD+[+/-](CMD加加号或减号)直接调整字体大小,非常方便,后来用 VSCode,字体大 ...

  6. Linux删除大于/小于固定大小的文件等

    删除目录下大小为0的文件 rm -f 删除当前目录下面所有 test 文件夹下面的文件 find ./ -name "test" -type d -exec rm -rf {} ; ...

  7. luogu P4719 【模板】动态 DP 矩阵乘法 + LCT

    方法二:LCT+矩阵乘法 上文中,我们用线段树来维护重链上的各种矩阵转移. 第二种方法是将树链剖分替换为动态树. 我们知道,矩阵乘法 $\begin{bmatrix} F_{u,0} & F_ ...

  8. appium+python,app自动化测试框架

    目前正在写一个app的自动化UI测试框架,目录结构如, 脚本还在调试,实现的方法是从excel表格读取测试用例,执行完成后会将结果保存到Excel中. 等待.......

  9. 【剑指Offer】62、二叉搜索树的第k个结点

      题目描述:   给定一棵二叉搜索树,请找出其中的第k小的结点.例如(5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4.   解题思路:   本题实际上比较简单,主要还是考察对 ...

  10. vfs:open.c 源码学习

    nameidata路径查找辅助结构 open.c @do_sys_open @get_unused_fd_flags @do_filp_open 1.开始填充nameidata 2.开始填充file ...