【深度优先搜索】【图论】【推荐】332. 重新安排行程

作者推荐

动态规划的时间复杂度优化

本文涉及知识点

深度优先搜索 图论

LeetCode332. 重新安排行程

给你一份航线列表 tickets ,其中 tickets[i] = [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。
所有这些机票都属于一个从 JFK(肯尼迪国际机场)出发的先生,所以该行程必须从 JFK 开始。如果存在多种有效的行程,请你按字典排序返回最小的行程组合。
例如,行程 [“JFK”, “LGA”] 与 [“JFK”, “LGB”] 相比就更小,排序更靠前。
假定所有机票至少存在一种合理的行程。且所有的机票 必须都用一次 且 只能用一次。

示例 1:
在这里插入图片描述

输入:tickets = [[“MUC”,“LHR”],[“JFK”,“MUC”],[“SFO”,“SJC”],[“LHR”,“SFO”]]
输出:[“JFK”,“MUC”,“LHR”,“SFO”,“SJC”]
示例 2:
在这里插入图片描述

输入:tickets = [[“JFK”,“SFO”],[“JFK”,“ATL”],[“SFO”,“ATL”],[“ATL”,“JFK”],[“ATL”,“SFO”]]
输出:[“JFK”,“ATL”,“JFK”,“SFO”,“ATL”,“SFO”]
解释:另一种有效的行程是 [“JFK”,“SFO”,“ATL”,“JFK”,“ATL”,“SFO”] ,但是它字典排序更大更靠后。

提示:
1 <= tickets.length <= 300
tickets[i].length == 2
fromi.length == 3
toi.length == 3
fromi 和 toi 由大写英文字母组成
fromi != toi

基础知识

定义

如果图G中的一个路径包括每个边恰好一次,则该路径称为欧拉路径(Euler path)。
如果一个回路是欧拉路径,则称为欧拉回路(Euler circuit)。

性质

性质一:一个有向图是欧拉回路 ⟺ \iff 所有顶点的入度等于出度且该图是连通图。
性质二:一个有向图是欧拉路径 ⟺ \iff 起点出度等于入度+1,终点入度=出度+1,其它顶点的入度等于出度且该图是连通图。
欧拉路径和回路符合性质比较简单,不证明。下面只证明性质一必定是欧拉回路,性质二是欧拉路径。

证明一

设有向图G符合性质一。
操作一:以任意定点为起点s,选取s的任意临接点n1,删除sn1后,除s外,其它顶点都是出度等于入度,就是进入后,一定会离开。由于顶点的出度和入度是有限的,所以一定会结束,而结束点一定是s(因为只有它入度大于出度)。设删除经过的路径为P1。
最后一次经过s后,可能有些点入度并不为0。
→ { ∗ ∗ 操作二 ∗ ∗ 图 G 删除 P 1 各边,此时余下的边 P 2 仍然符合性质一。 P 1 经过的各点,一定有点 n 2 出度不为 0 。否则与连通图矛盾。 \rightarrow\begin{cases}**操作二**图G删除P1各边,此时余下的边P2仍然符合性质一。\\ P1经过的各点,一定有点n2出度不为0。否则与连通图矛盾。\\ \end{cases} {操作二G删除P1各边,此时余下的边P2仍然符合性质一。P1经过的各点,一定有点n2出度不为0。否则与连通图矛盾。
操作二时:如果有重边,经过几次则删除几条。
以n2为起点对P2进行操作一,得到P3,必定以n2开始和结尾。
用P3替换P1的n2节点。如此往复直到所有节点出度入度为0。

证明二

设有向图G符合性质二,s出度=入度+1,e入度=出度+1。一定存在以s为起点,e为终点的路径P1。选取方法类似证明一,多个出边任选一条出边。图G删除P1后,为P2;P2要么为空,要么符合性质二。

深度优先搜索

题目确保某条从JFK为起点的路径是欧拉路径。
如果是欧拉环路:所有点出度等于入度。
如果不是环路:起点出度-1==入度 终点入度=出度+1,其它节点入度等于出度。
必须确保起点最后访问终点那一支,其它访问顺序按字典需。

DFS 函数

在这里插入图片描述

主函数

DFS(“JFK”)
颠倒m_vRes的顺序
返回m_vRet。

示例和时序图

在这里插入图片描述
在这里插入图片描述

按时间线访问m_vRes的顺序:DAFEACBA。转置(颠倒顺序)后为:ABCAEFAD。

证明:

假定图G的欧拉路径最后一个出度大于1的节点为c,它共有m+1+n条出边,按邻接字典序排序后,第m+1条出边指向终点e。
步骤一:只讨论节点c及之后的路径。设c的临接点按字典序分别为:n[1] …n[m+n+1]。
除DFS(n[1+m] → \rightarrow e)可以直接结束,其它节点都必须等所有A的出边都访问结束(包括n[1+m]),所以 n[1+m] → \rightarrow e 的逆序最先加到vRet。
c → \rightarrow n[n+m+1]是c最后一条出边,故将 n[i+m+1] → \rightarrow c 的逆序放到vRet 中。
c → \rightarrow n[n+m ]是c最倒数第二条出边,故将 n[i+m] → \rightarrow c 的逆序放到vRet 中。
⋯ \cdots 将 n[1+m+1] → \rightarrow c 的逆序放到vRet 中。
⋮ \vdots
⋯ \cdots 将 n[m] → \rightarrow c 的逆序放到vRet 中。
⋯ \cdots n[1 ] → \rightarrow c 的逆序放到vRet 中。
将c 放到vRet 中。
步骤二:将图G 节点c及之后节点的出边都删除。c变成新的终点。
不断持续步骤一二到所有节点的出度为1。注意:c等于e也符合。

代码

核心代码

class Solution {
public:vector<string> findItinerary(vector<vector<string>>& tickets) {std::unordered_map<string, multiset<string>> mNeiBo;for (const auto& v : tickets){mNeiBo[v[0]].emplace(v[1]);}DFS(mNeiBo, "JFK");std::reverse(m_vRet.begin(), m_vRet.end());return m_vRet;}void DFS(std::unordered_map<string, multiset<string>>& mNeiBo,const string& cur){while (mNeiBo[cur].size()){auto next = *mNeiBo[cur].begin();mNeiBo[cur].erase(mNeiBo[cur].begin());DFS(mNeiBo, next);}m_vRet.emplace_back(cur);}vector<string> m_vRet;
};

测试用例

template<class T,class T2>
void Assert(const T& t1, const T2& t2)
{assert(t1 == t2);
}template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{if (v1.size() != v2.size()){assert(false);return;}for (int i = 0; i < v1.size(); i++){Assert(v1[i], v2[i]);}}int main()
{vector<vector<string>> tickets;{Solution sln;tickets = { {"MUC","LHR"},{"JFK","MUC"},{"SFO","SJC"},{"LHR","SFO"} };auto res = sln.findItinerary(tickets);Assert({ "JFK","MUC","LHR","SFO","SJC" }, res);}{Solution sln;tickets = { {"JFK","SFO"},{"JFK","ATL"},{"SFO","ATL"},{"ATL","JFK"},{"ATL","SFO"} };auto res = sln.findItinerary(tickets);Assert({ "JFK","ATL","JFK","SFO","ATL","SFO" }, res);}
}

2023年4月

class Solution {
public:vector<string> findItinerary(vector<vector<string>>& tickets) {		for (const auto& v : tickets){m_vNeiB[v[0]].emplace(v[1]);}dfs("JFK");std::reverse(m_vRet.begin(), m_vRet.end());return m_vRet;}void dfs(const string& sCur){while (m_vNeiB.count(sCur) && m_vNeiB[sCur].size()){const string sNext = m_vNeiB[sCur].top();m_vNeiB[sCur].pop();dfs(sNext);}m_vRet.emplace_back(sCur);}std::unordered_map < string, std::priority_queue<string, vector<string>, greater<string>>> m_vNeiB;vector<string> m_vRet;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快

速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关

下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/498471.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL进阶:大厂高频面试——各类SQL语句性能调优经验

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;MySQL进阶&#xff1a;强推&#xff0c;冲大厂必精通&#xff01;MySQL索引底层&#xff08;BTree&#xff09;、性能分析、使用…

云时代【3】—— 容器技术发展史

云时代【3】—— 容器技术发展史 一、容器技术发展史&#xff08;一&#xff09;OCI 规范 与 RunC&#xff08;二&#xff09;CRI 与 Container Runtime1. CRI 标准2. Container Runtime&#xff08;1&#xff09;为什么需要 Container Runtime&#xff08;2&#xff09;什么是…

价格腰斩:腾讯云服务器优惠价格表,不看后悔!

腾讯云服务器多少钱一年&#xff1f;62元一年起&#xff0c;2核2G3M配置&#xff0c;腾讯云2核4G5M轻量应用服务器218元一年、756元3年&#xff0c;4核16G12M服务器32元1个月、312元一年&#xff0c;8核32G22M服务器115元1个月、345元3个月&#xff0c;腾讯云服务器网txyfwq.co…

springboot+vue实现Minio文件存储

安装minio 首先点击进入MINIO官网&#xff0c;进行一个minio服务器的下载 下载好了之后在本地磁盘找一个文件夹&#xff0c;把下载的exe放入文件夹&#xff0c;再新建一个文件夹准备存放数据和文件 在当前目录cmd进入控制台&#xff0c;输入代码 minio.exe server data成功后…

2-溴叠氮,1-azido-2-bromoethane,可以与醇或酚反应生成相应的叠氮化物

2-溴叠氮&#xff0c;1-azido-2-bromoethane&#xff0c;1-Azido-2-bromo&#xff0c;可以与醇或酚反应生成相应的叠氮化物 您好&#xff0c;欢迎来到新研之家 文章关键词&#xff1a;2-溴叠氮&#xff0c;1-azido-2-bromoethane&#xff0c;1-Azido-2-bromo&#xff0c;1 Az…

使用vue把一周的时间划分为可以选择多个阶段

提示&#xff1a;使用vue把一周的时间划分为可以选择多个阶段段&#xff08;亲测有效&#xff09; 一、直接复制以下代码 代码如下&#xff08;示例&#xff09;&#xff1a; <template><div class"byted-weektime" mousedown"dian" mousemove&qu…

第四十五回 病关索大闹翠屏山 拚命三火烧祝家店-Python函数接受任意关键字参数

官府得到上报&#xff0c;被杀死的僧人是报恩寺的裴如海&#xff0c;旁边的头陀是寺后面的人叫胡道。孔目说他们两个互相杀死&#xff0c;没有其他人什么事&#xff0c;这件事也就过去了。 杨雄听说了这件事&#xff0c;知道是石秀干的&#xff0c;找石秀为自己错怪他道歉。两…

请你画出一个微服务项目架构图

第一种 架构图 第二种 架构图

为您提供互联网一站式服务代采系统

1688跨境“寻源通”产品背景 11月19日, 1688跨境“寻源通”产品发布会在杭州举办。 1688跨境“寻源通”分别针对跨境ERP、跨境代采商、跨境超买和SaaS,为他们提供基于 AI 技术的搜索比价引擎,通过和官方合作把1688 的1亿官方源头货盘铺出去。 该计划的推出是为了解决跨境生意…

【Ansys Fluent Web 】全新用户界面支持访问大规模多GPU CFD仿真

基于Web的技术将释放云计算的强大功能&#xff0c;加速CFD仿真&#xff0c;从而减少对硬件资源的依赖。 主要亮点 ✔ 使用Ansys Fluent Web用户界面™&#xff08;UI&#xff09;&#xff0c;用户可通过任何设备与云端运行的仿真进行远程交互 ✔ 该界面通过利用多GPU和云计算功…

项目流程图

实现便利店自助付款项目 服务器&#xff1a; 1、并发服务器&#xff08;多进程、多线程、IO多路复用&#xff09; 2、SQL数据库的创建和使用&#xff08;增删改查&#xff09; 3、以模块化编写项目代码&#xff0c;按照不同模块编写.h/.c文件 客户端&#xff1a; 1、QT客户端界…

面试官:说一下Filter过滤器的执行顺序

背景说明 各位小伙伴大家好&#xff0c;我是全栈小白 相信各位小伙伴都用过Filter过滤器吧&#xff0c;在学习servlet的时候&#xff0c;Filter可是我们认证的好帮手&#xff0c;但是在学习了SpringBoot框架之后&#xff0c;Filter可能被大家遗忘了&#xff0c;相对Spring框架…