题目大意:

给定一张航空图,图中顶点代表城市,边代表 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. CSS布局——三栏布局

    说到三栏布局,很多都会提到圣杯布局和双飞翼布局这两个经典的三栏布局方式.于是,我在网上搜了一些相关资料,阅读并跟着代码敲了一遍,发现在处理三栏布局上,他们采用的都是两边栏固定,中间栏自适应的策略.在处 ...

  2. Android项目实战_手机安全卫士home界面

    # 安全卫士主页面# ###1.GridView控件 1.与ListView的使用方式差不多,也要使用数据适配器,通过设置android:numColumns控制显示几列 2.通过指定android: ...

  3. java攻城师之路--复习java web之servlet

    需要掌握的知识点:1.Servlet程序编写 ----- 生命周期2.ServletAPI Request Response 3.Cookie 和 Session Servlet 用来 动态web资源 ...

  4. sql 分析 依赖beanutils

    你还在为sql语句的拼接而烦恼吗? sql语句支持表达式了! package com.newland.bi.webservice.common.manage; import java.util.Arr ...

  5. JavaScript定时器及其他

    By Abyssly Jun 20 2014 Updated:Jun 20 2014 平时工作中不可避免地要嵌套网页,对JavaScript的深入了解还是很有必要滴.而JavaScript中一个容易让 ...

  6. C# 时间对比

    public bool IfTime(string StartTime, string EndTime) { DateTime dt1 = Convert.ToDateTime(StartTime); ...

  7. rsync 3.1.3

    rsyncd.conf 2018年1月28日 rsyncd配置(5) 2018年1月28日 姓名 rsyncd.conf配置rsync守护进程的方式在file for 概要 rsyncd.conf 描 ...

  8. pandas操作,按序号取列,按条件筛选,df格式转换等

    这几天遇到比较多的dataframe操作,频繁使用,在此整理记录下,方便查找. 1.num为列的数字序号,name=df.columns[num],返回的是column的字符串名字,df[name]= ...

  9. Luogu P2866 [USACO06NOV]糟糕的一天Bad Hair Day

    P2866 [USACO06NOV]糟糕的一天Bad Hair Day 题目描述 Some of Farmer John's N cows (1 ≤ N ≤ 80,000) are having a ...

  10. 让TP5.0在SWOOLE上飞起来

    TP-SWOOLE 目前,TP5.1官方已经提供了think-swoole2.0,集成程度以前优雅很多,不过5.0的集成方式确实有些鸡肋.所以看了下2.0,为5.0开发了一个扩展包,可以采用compo ...