点击上方“蓝字”,发现更多精彩。背景
01PART解题思路本题本质即为不重复的遍历完图中的所有边,即 “只一笔描完图中所有边,且不重复”。①.首先把图的边缘列表转成邻接列表,以方便遍历每个节点的每条边。②.用状态标记每条边是否走过,可以避免对容器进行插入\删除元素时出现迭代器失效问题。③.map 默认是按字典升序排序。④.使用 DFS 遍历所有边,遍历到底不符合要求则撤销当前状态。02PART代码示例
class Solution {public: unordered_map<string,map<string,int>> tickmp;// 出发地---[目的地---剩余票数] int tickCount;//票的总数 vector<string> res;//保存结果 vector<string> findItinerary(vector<vector<string>>& tickets) { tickCount = tickets.size();//初始化票总数 //初始化邻接列表 for( int i = 0;i < tickets.size();i++) { // A --> B string A = tickets[i][0]; string B = tickets[i][1]; tickmp[A][B]++; } res.push_back("JFK"); dfs("JFK"); return res; } //检查从一个起点出发是否还有票 bool chekHazDes( const string &fromStr){ if( tickmp[fromStr].size() == 0) return false; for( auto it = tickmp[fromStr].begin();it != tickmp[fromStr].end();++it) { if( it->second > 0) return true; } return false; } bool dfs(const string &fromStr){ if( tickmp.find(fromStr) == tickmp.end() || !chekHazDes(fromStr))//没有可选的目的地了 { if( tickCount == 0)//所有票用完了 return true; else return false; } //遍历当前能做的所有选择、依次选择从当前起点出发的每一张票 for( auto it = tickmp[fromStr].begin();it != tickmp[fromStr].end();++it ) { if( it->second == 0)//该票已经用过 continue; string toStr = it->first;//目的地 res.push_back(toStr);//加入到结果 --tickCount;//剩余票数减一 it->second--;//当前起点与目的地的票数减一 bool isok = dfs(toStr); if( isok ) return true; else { //撤销上次结果 it->second++; ++tickCount; res.pop_back(); } } return false; }};
Hierholzer算法01PART基本概念
①.欧拉路径:如果在一张图中,可以从一点出发遍历所有的边,那么遍历过程中的这条路径就叫做欧拉路径。
②.欧拉回路:如果欧拉路径是闭合的,则成为欧拉回路。
③.欧拉图:具有欧拉回路的图。
④.半欧拉图:有欧拉路径但没有欧拉回路的图称为半欧拉图。
无向图中,如果所有顶点的度数都为偶数,则为欧拉图;如果有两个顶点的度数为奇数,其他的为偶数,则为半欧拉图。 有向图中,如果所有顶点的入度等于出度,那么就是欧拉图。如果恰有一个顶点出度和入度差为 1 且其他顶点的入度和出度相同,则为半欧拉图。02PART算法步骤Hierholzer 算法的一般过程为:
①.选择任一顶点为起点,遍历所有相邻边。
②.深度搜索,访问相邻顶点。将经过的边都删除。
③.如果当前顶点没有相邻边,则将顶点入栈。
④.栈中的顶点倒序输出,就是从起点出发的欧拉回路。
03PART代码示例class Solution {public: unordered_map<string, priority_queue<string, vector<string>, std::greater<string>>> vec; vector<string> stk; void dfs(const string& curr) { while (vec.count(curr) && vec[curr].size() > 0) { string tmp = vec[curr].top(); vec[curr].pop(); dfs(move(tmp)); } stk.emplace_back(curr); } vector<string> findItinerary(vector<vector<string>>& tickets) { for (auto& it : tickets) { vec[it[0]].emplace(it[1]); } dfs("JFK"); reverse(stk.begin(), stk.end()); return stk; }};
扫码关注持续获取最新文章c++学习 算法与数据结构