Accepted date: 2016-07-28
Run Time: 0.000
Ranking (as of 2016-07-28): 145 out of 492
Language: C++
/*
UVa 157 - Route Finding
To build using Visual Studio 2012:
cl -EHsc -O2 UVa_157_Route_Finding.cpp
*/
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <limits>
#include <cstdio>
using namespace std;
const int infinite = numeric_limits<int>::max();
const int nr_letters = 'z' - 'a' + 1, n_max = nr_letters * nr_letters;
struct edge {
int v_;
int w_;
edge(int v, int w) : v_(v), w_(w) {}
};
vector<edge> edges[n_max];
bool visited[n_max];
int distances[n_max], parents[n_max];
struct distance_comparator {
bool operator() (int i, int j) const
{
return (distances[i] != distances[j]) ? distances[i] < distances[j] : i < j;
}
};
int dijkstra_shortest_path(int n, int start, int end)
{
for (int i = 0; i < n; i++)
visited[i] = false, distances[i] = infinite;
set<int, distance_comparator> pq; // priority queue
distances[start] = 0, parents[start] = -1;
pq.insert(start);
while(!pq.empty()) {
int u = *pq.begin();
pq.erase(pq.begin());
visited[u] = true;
if (u == end)
break;
int d = distances[u], pw = (u != start) ? d - distances[parents[u]] : -1;
const vector<edge>& es = edges[u];
for (size_t i = 0, j = es.size(); i < j; i++) {
int v = es[i].v_, w = es[i].w_;
if (w == 3 && (pw == 3 || pw == 0)) // pass through several connections
w = 0;
if (!visited[v] && distances[v] > d + w) {
pq.erase(v); // remove v if it has already been in the queue
distances[v] = d + w, parents[v] = u;
pq.insert(v);
}
}
}
return distances[end];
}
map<pair<char, char>, int> vertices;
map< int, pair<char, char> > stations;
int get_vertex(char cr, char cs)
{
pair<map<pair<char, char>, int>::iterator, bool> result =
vertices.insert(make_pair(make_pair(cr, cs), static_cast<int>(vertices.size())));
if (result.second)
stations.insert(make_pair(result.first->second, make_pair(cr, cs)));
return result.first->second;
}
void print_path(int u, int w, char& cr)
{
pair<int, int> s = stations[u];
if (parents[u] == -1) {
cr = s.first;
printf("%c%c", cr, s.second);
}
else {
print_path(parents[u], distances[u] - distances[parents[u]], cr);
if (w) {
if (s.first != cr) {
cr = s.first;
printf("=%c%c", cr, s.second);
}
else
putchar(s.second);
}
}
}
int main()
{
string s;
getline(cin, s);
istringstream iss(s);
int nr_routes;
iss >> nr_routes;
vertices.clear();
while (nr_routes--) {
getline(cin, s);
const char* p = s.c_str();
char cr = *p++;
int u = get_vertex(cr, *++p), su = u, v;
for (p++; *p; p++) {
if (*p == '=') { // ...hc=Bg=Cc=Abd...
int ccr = *++p;
v = get_vertex(ccr, *++p);
if (v != su)
edges[u].push_back(edge(v, 3)), edges[v].push_back(edge(u, 3));
else
edges[u].push_back(edge(v, 1)), edges[v].push_back(edge(u, 1));
}
else {
v = get_vertex(cr, *p);
edges[u].push_back(edge(v, 1)), edges[v].push_back(edge(u, 1));
u = v;
}
}
}
int n = static_cast<int>(vertices.size());
while (getline(cin, s) && s[0] != '#') {
int start = get_vertex(s[0], s[1]), end = get_vertex(s[2], s[3]);
int d = dijkstra_shortest_path(n, start, end);
printf("%3d: ", d);
char cr;
print_path(end, -1, cr);
putchar('\n');
}
return 0;
}