题目大意:

给定一张航空图,图中顶点代表城市,边代表 2 城市间的直通航线。现要求找出一条满足下述限制条件的且途经城市最多的旅行路线。
(1)从最西端城市出发,单向从西向东途经若干城市到达最东端城市,然后再单向从东向西飞回起点(可途经若干城市)。
(2)除起点城市外,任何城市只能访问 1 次。

关键字:网络流 方向等效转换 拆点 不交叉路径 特判

网络流:1个人旅行的过程可以看作以流量为1流动的过程。

方向等效转化:本问题可以看作两个人同时从最西的城市走向最东的城市,每个人占有1个流量,总流量为2。

拆点:题中说每个城市只经过一次,因此把一个城市看作容量为1的边,如果西东两个城市之间有航线,则把西城to节点连东城from节点,容量为1。为保证总流量为2,最西城边容量和最东城容量为2。

不交叉路径:流量为1,即可保证路径不交叉

特判:如果最西城与最东城有航线,则边的容量为2。

#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <cassert>
#include <map>
#include <string>
#include <iostream>
using namespace std; //#define test
#define INF 0x3f3f3f3f
#define LOOP(i,n) for(int i=1; i<=n; i++)
const int MAX_CITY = , MAX_EDGE = MAX_CITY*MAX_CITY + MAX_CITY * , MAX_NODE = MAX_CITY * ;
map<string, int> loc;
string Cities[MAX_CITY];
bool Vis[MAX_CITY];
int TotCity, TotLine; struct MCMF
{
struct Node;
struct Edge; struct Node
{
int Id;
Edge *Head, *Prev;
int Dist;
bool Inq; void Init()
{
Prev = NULL;
Dist = INF;
Inq = false;
}
}; struct Edge
{
int Cap, Cost;
Node *From, *To;
Edge *Next, *Rev;
Edge(int cap, int cost, Node *from, Node *to, Edge *next) :Cap(cap), Cost(cost), From(from), To(to), Next(next){}
}; Node _nodes[MAX_NODE];
Edge *_edges[MAX_EDGE];
int _vCount = , _eCount = ;
Node *Start, *Sink;
int TotFlow, TotCost; void Reset(int n, int sId, int tId)
{
_vCount = n;
_eCount = ;
Start = &_nodes[sId], Sink = &_nodes[tId];
TotFlow = TotCost = ;
} Edge* AddEdge(Node *from, Node *to, int cap, int cost)
{
Edge *cur = _edges[++_eCount] = new Edge(cap, cost, from, to, from->Head);
from->Head = cur;
return cur;
} void Build(int uId, int vId, int cap, int cost)
{
Node *u = &_nodes[uId], *v = &_nodes[vId];
u->Id = uId;
v->Id = vId;
Edge *edge1 = AddEdge(u, v, cap, cost);
Edge *edge2 = AddEdge(v, u, , -cost);//遗忘点*2:-cost
edge1->Rev = edge2;
edge2->Rev = edge1;
} bool SPFA()
{
queue<Node*> q;
for (int i = ; i <= _vCount; i++)
_nodes[i].Init();
Start->Dist = ;
q.push(Start);
while (!q.empty())
{
Node *u = q.front();
q.pop();
u->Inq = false;//易忘点
for (Edge *e = u->Head; e; e = e->Next)
{
if (e->Cap && u->Dist + e->Cost < e->To->Dist)//易忘点*2:e->Cap
{
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;
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;
TotCost += minFlow * e->Cost;
#ifdef test
printf("%d-%d Cost %d restCap %d\n", e->From->Id, e->To->Id, e->Cost*minFlow, e->Cap);
#endif
}
#ifdef test
printf("TotFlow %d TotCost %d\n", TotFlow, TotCost);
#endif
}
} int GetFlow()
{
return TotFlow;
} int GetCost()
{
return TotCost;
}
}g; void print1()
{
MCMF::Node *cur = + g._nodes;
while (cur->Id != TotCity)
{
Vis[cur->Id] = true;
cout << Cities[cur->Id] << endl;
cur = cur->Id + TotCity + g._nodes;
for (MCMF::Edge *e = cur->Head; e; e = e->Next)
{
if (!e->Cap && !Vis[e->To->Id] && e->To->Id > cur->Id-TotCity)
{
cur = e->To;
break;
}
}
}
} void print2(int id)
{
if (id == TotCity)
{
cout << Cities[id] << endl;
return;
}
Vis[id] = true;
MCMF::Node *cur = id + TotCity + g._nodes;
for (MCMF::Edge *e = cur->Head; e; e = e->Next)
{
if (!e->Cap && !Vis[e->To->Id] && e->To->Id > cur->Id - TotCity)
{
print2(e->To->Id);
break;
}
}
cout << Cities[id] << endl;
} int main()
{
#ifdef _DEBUG
freopen("c:\\noi\\source\\input.txt", "r", stdin);
#endif
int sId, tId;
string s1, s2;
scanf("%d%d", &TotCity, &TotLine);
sId = ;
tId = TotCity * ;
g.Reset(tId, sId, tId);
LOOP(city, TotCity)
{
cin >> Cities[city];
loc.insert(pair<string, int>(Cities[city], city));
if (city == || city == TotCity)
g.Build(city, city + TotCity, , -);
else
g.Build(city, city + TotCity, , -);
}
LOOP(line, TotLine)
{
cin >> s1 >> s2;
int p1 = loc[s1], p2 = loc[s2];
if (p2 < p1)
swap(p1, p2);
if (p1 == && p2 == TotCity)
g.Build(p1+TotCity, p2, , );
else
g.Build(p1+TotCity, p2, , );
}
g.Proceed();
if (g.TotFlow<)
{
cout << "No Solution!" << endl;
return ;
}
printf("%d\n", -g.TotCost-);
LOOP(v, g._vCount)
g._nodes[v].Inq = false;
print1();
print2();
return ;
}

luogu2770 航空路线问题 网络流的更多相关文章

  1. luogu2770 航空路线问题

    前置技能:HDU3376 Matrix Again 所以看到这个题,我们也会想着用最大费用最大流解决,因为从起点飞到终点再飞回来,就等于从起点飞两次到终点且这两次飞行除了起点终点之外没有访问超过一次的 ...

  2. loj #6122. 「网络流 24 题」航空路线问题

    #6122. 「网络流 24 题」航空路线问题 题目描述 给定一张航空图,图中顶点代表城市,边代表两个城市间的直通航线.现要求找出一条满足下述限制条件的且途经城市最多的旅行路线. 从最西端城市出发,单 ...

  3. 【题解】【网络流24题】航空路线问题 [P2770] [Loj6122]

    [题解][网络流24题]航空路线问题 [P2770] [Loj6122] 传送门:航空路线问题 \([P2770]\) \([Loj6122]\) [题目描述] 给出一张有向图,每个点(除了起点 \( ...

  4. JS前端三维地球渲染——中国各城市航空路线展示

    前言 我还从来没有写过有关纯JS的文章(上次的矢量瓦片展示除外,相对较简单.),自己也学习过JS.CSS等前端知识,了解JQuery.React等框架,但是自己艺术天分实在不过关,不太喜欢前端设计,比 ...

  5. 网络流 P2770 航空路线问题

    #include <cstdio> #include <cstdlib> #include <map> #include <queue> #includ ...

  6. 【刷题】LOJ 6122 「网络流 24 题」航空路线问题

    题目描述 给定一张航空图,图中顶点代表城市,边代表两个城市间的直通航线.现要求找出一条满足下述限制条件的且途经城市最多的旅行路线. 从最西端城市出发,单向从西向东途经若干城市到达最东端城市,然后再单向 ...

  7. 【网络流24题】No.11(航空路线问题 最长不相交路径 最大费用流)

    [题意] 给定一张航空图, 图中顶点代表城市, 边代表 2 城市间的直通航线. 现要求找出一条满足下述限制条件的且途经城市最多的旅行路线.(1) 从最西端城市出发,单向从西向东途经若干城市到达最东端城 ...

  8. 【PowerOJ1746&网络流24题】航空路线问题(费用流)

    题意: 思路: [问题分析] 求最长两条不相交路径,用最大费用最大流解决. [建模方法] 把第i个城市拆分成两个顶点<i.a>,<i.b>. 1.对于每个城市i,连接(< ...

  9. LG2770/LOJ6122 航空路线问题 费用流 网络流24题

    问题描述 LG2770 LOG6122 题解 教训:关掉流同步之后就不要用其他输入输出方式了. 拆点. 两个拆点之间连\((1,1)\),其他连\((1,0)\) \(\mathrm{Code}\) ...

随机推荐

  1. fcc html5 css 练习1

    font-size:  字号 利用link导入新字体再引用<link href="https://fonts.gdgdocs.org/css?family=Lobster" ...

  2. Android项目实战_手机安全卫士拦截骚扰

    ###1.骚扰拦截需求分析1.界面1.1 黑名单列表界面1.2 添加黑名单界面2.功能2.1 黑名单的添加.删除2.2 拦截电话2.3 拦截短信 ###2.黑名单数据库的创建1.分析需要的字段id 主 ...

  3. echarts交叉关系图一

    想要做一个公司-人员关系图,官网echarts图graph webkit dep 稍微改了一下, 也是有点恶心自己,调了一个数据最多的去改,如果正好有人需要就不用去改了 说明:此图没有坐标,可以设置图 ...

  4. 贴一段自动编译java,并混淆编译的代码

    刚写的一个自动编译.混淆.打包jar的代码,做个记录 用到的NuGet: <?xml version="1.0" encoding="utf-8"?> ...

  5. 为什么阿里规约手册要求谨慎使用Arrays.asList方法

    前言 在开发中,有时候会碰到把多个参数,或者说把数组转成List的需求,通常我们会使用 Arrays.asList()方法.但是该方法在使用的过程中,稍有不慎就会出现严重的异常.有如下代码: @Tes ...

  6. 可以用作javascript异步模式的函数写法

    1. 回调函数 f1(); f2(); function f1(callback) { setTimeout(function() { // f1的任务代码 callback(); }, 1000); ...

  7. ThinkPHP框架表单验证AJAX

    验证有两种方式:静态验证与动态验证. 一.静态验证 在模型类里面预先定义好该模型的自动验证规则,我们称为静态定义. 验证时要在test表的Model里面加验证条件:新建testModel.class. ...

  8. 程序员不可不知的Linux性能工具

    前言 在实际开发中,有时候会收到一些服务的监控报警,比如CPU飙高,内存飙高等,这个时候,我们会登录到服务器上进行排查.本篇博客将涵盖这方面的知识:Linux性能工具. 一次线上问题排查模拟 背景:服 ...

  9. python学习笔记--关于函数的那点事1

    函数参数 1.位置参数 类似于java函数的基本参数,按照顺序和结构定义参数 2.默认参数 def method(param,defaultParam=defaultValue) 调用时,可以调用me ...

  10. select 多选 和单选,分组

    <select name="group"> <option value="1">北京</option> <option ...