题目大意:地球与月球间有可容纳无限人的太空站,还有在太空站与星球间按周期行驶的、有固定容量的太空船,每一艘太空船从一个太空站驶往任一太空站耗时均为 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. 自己写的_top、_parent以及对iframe和frameset的理解

    iframe可以写在<body>标签里,如<body><iframe src="xxx"  name="xxx" style=&q ...

  2. ViewPager PagerAdapter 的使用

    1: 目的,实现全屏滑动的效果 2:类似于BaseAdapter public class MyPagerAdapter extends PagerAdapter { private Context ...

  3. 如何通过WallpaperManager(壁纸管理器)设置与修改壁纸?

    WallpaperManager(壁纸管理器),是手机壁纸相关的一个API的相关类.其设置壁纸常有如下三种方法可调用: - setBitmap(Bitmap bitmap):将壁纸设置为bitmap所 ...

  4. Linux 与 Windows 文件互传(VMWare)

    虚拟机无桌面的Linux 与 物理机Windows 文件互传有很多种方法,现在先说一种通过共享文件夹的形式,其他方法后续再补充 1.     背景 1)        虚拟机系统:VMWare无桌面的 ...

  5. oracle从入门到精通复习笔记

    为方便大家跟着我的笔记练习,为此提供数据库表文件给大家下载:点我下载 描述一个表用 desc employees过滤重复的部门 select distinct department_id from e ...

  6. halcon 模板匹配 -- 转化 vector_angle_to_rigid

    ********************************模板匹配 ********************create_shape_model创建模板,这个函数有许多参数,其中金字塔的级数由N ...

  7. Verification之PSL之use

    1 Where can PSL be used? • Documentation – Requirements – RTL Designs • Controllers – Memories, FIFO ...

  8. OpenCV边缘检测的详细参数调节

    1. findCountours 转载于http://blog.sina.com.cn/s/blog_7155fb1a0101a90h.html findContours函数,这个函数的原型为: &l ...

  9. OpenCV的AdaptiveThreshold函数

    摘自于OpenCV Doc2.410,opencv2refman文档. 1.函数原型 adaptiveThreshold //Applies an adaptive threshold to an a ...

  10. C# 检测字符串是否为数字

    long n; 1. ], ].All(char.IsDigit); //识别空字符时候 会认为是数字 string str0 = ""; string str1 = " ...