I struggled a while for looking the best data structure to do this DFS... the following is the best solution I think....
#include <string>
#include <vector>
#include <unordered_map>
#include <set>
#include <algorithm>
#include <iostream>
using namespace std;
/*
Given a list of airline tickets represented by pairs of departure and arrival airports[from, to]
reconstruct the itinerary in order. All of the tickets belong to a man who departs from JFK. Thus
the itinerary must begin with JFK.
Example 1:
tickets = [["MUC", "LHR"], ["JFK", "MUC"], ["SFO", "SJC"], ["LHR", "SFO"]]
Return ["JFK", "MUC", "LHR", "SFO", "SJC"].
Example 2:
tickets = [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]]
Return ["JFK","ATL","JFK","SFO","ATL","SFO"].
Another possible reconstruction is ["JFK","SFO","ATL","JFK","ATL","SFO"]. But it is larger in lexical order.
*/
// It is better to use multiset STL to solve this problem, so that we dont need to sort the order.
vector<string> findItinerary(vector< pair<string, string> >& tickets) {
unordered_map< string, multiset<string> > itinerary;
for(int i = 0; i < tickets.size(); ++i) {
itinerary[tickets[i].first].insert(tickets[i].second);
}
// since right now the itinerary have been constructed. we need to DFS search the graph, but once we visited the node, we need to delete it from the multiset to avoid duplicate visit.
vector<string> res;
res.push_back("JFK");
vector<string> result;
while(res.size() > 0) {
string from = res.back();
if(itinerary.count(from) && itinerary[from].size() > 0) {
multiset<string>& to = itinerary[from];
res.push_back(*to.begin());
to.erase(to.begin());
} else {
result.push_back(from);
res.pop_back();
}
}
reverse(result.begin(), result.end());
return result;
}
int main(void) {
vector< pair<string, string> > inputs{{"MUC", "LHR"}, {"JFK", "MUC"}, {"SFO", "SJC"}, {"LHR", "SFO"}};
vector<string> res = findItinerary(inputs);
for(int i = 0; i < res.size(); ++i) cout << res[i] << endl;
}