题目大意:

给定一张航空图,图中顶点代表城市,边代表 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. 把多种验证规则用到一个model上

    基于标记特性的Model验证,真的太棒了,与jquery validate结合后激情四射,有木有,一句话完成前后端验证.简直让人秒爱... 但是爱是爱了,生活中总会有些小摩擦,这不问题来了:看图中那个 ...

  2. checkbox与文字混排无法对齐到一行的解决办法

    直接上代码: <span><input style="vertical-align:middle" type="checkbox" name= ...

  3. css图片特效

    网站图片往往有很多显示效果,使用css是实现图片特效的比较简便的方式.下面记录一段css鼠标指向的多重特效: <!DOCTYPE html><html lang="en&q ...

  4. IIS中实现http自动转换到https

    IIS中实现http自动转换到https修改以下文件:C:\WINDOWS\Help\iisHelp\common\403-4.htm 为以下内容<!DOCTYPE HTML PUBLIC &q ...

  5. python os os.path模块学习笔记

    #!/usr/bin/env python #coding=utf-8 import os #创建目录 os.mkdir(r'C:\Users\Silence\Desktop\python') #删除 ...

  6. mysql zip版本如何安装

    1.下载mysqlzip包并解压到D:\javadeveloper\mysql-5.6.24-winx642.配置环境变量在path中添加路径 D:\javadeveloper\mysql-5.6.2 ...

  7. css页面布局总结

    W3C标准:是万维网制定的一系列标准,包括结构化标准语言(html.xml),表现 标准语言(css),行为标准语言(DOM,ECMAScript<javascript>)组成.这个标准倡 ...

  8. 线索二叉树【C语言】

    #include<stdio.h> #include<stdlib.h> typedef char ElemType; typedef enum{Link,Thread} Po ...

  9. HDU1465 不容易系列之一&&HDU4535吉哥系列故事——礼尚往来

    HDU1465不容易系列之一 Problem Description 大家常常感慨,要做好一件事情真的不容易,确实,失败比成功容易多了!做好“一件”事情尚且不易,若想永远成功而总从不失败,那更是难上加 ...

  10. 史上最详细的CentOS 7 安装 HBase教程

    1. 前半部分参考 https://www.cnblogs.com/ivictor/p/5906433.html 2.问题 namenode无法启动,参考 https://stackoverflow. ...