/* vim: set ts=4 sts=4 sw=4 si foldmethod=marker: */ // {{{ stock programming challenge garbage // IO #include #include #include #include // Utility #include // Data structures //#include //#include #include //#include #include //#include // Utility typedefs // I want easy access to STL and things like hash_map using namespace std; //using namespace std::tr1; using namespace __gnu_cxx; // Needed for hash_map namespace __gnu_cxx { template<> struct hash { size_t operator()(const std::string& x) const { return hash()(x.c_str()); } }; } // }}} const int infinity(1000000); // for very small values of infinity struct Node { Node() : query(-2), erdosNumber(-1) { } void addLink(Node* node) { if (node != this) nodes.insert(node); // let set maintain uniqueness of connections } long query; int erdosNumber; set nodes; }; typedef hash_map hmsN; Node* addNode(hmsN& forest, const char* name) { hmsN::iterator loc(forest.find(name)); return (loc == forest.end()) ? forest[name] = new Node() : loc->second; } int visit(int query, Node* node, int distance) { // if we have it cached, return that if (-1 != node->erdosNumber) return node->erdosNumber + distance; // already visited by this source; we're in a loop if (node->query == query) return -1; // we've now visited this node node->query = query; int best(infinity); for (set::iterator i(node->nodes.begin()), ie(node->nodes.end()); i != ie; ++i) { int result(visit(query, *i, distance + 1)); if (result != -1 && result < best) best = result; } if (infinity != best) return best; return -1; } // improvements: whitespace trimming int main(int argc, char **argv) { long cases; cin >> cases; long scenario(1); char garbage[100][100]; while (cases--) { cout << "Scenario " << scenario++ << endl; long papers, queries; cin >> papers >> queries; cin.ignore(1000, '\n'); hash_map nodes; Node* npCache[100]; string line; while (papers--) { getline(cin, line); const char* i(line.c_str()); const char* j(i); // skip leading whitespace for (i = j; *i != '\0' && *i != ':' && *i == ' '; ++i); int countAuthors(0); bool skip(true); int count(0); while (*j != '\0' && *j != ':') { if (',' == *j) { if (skip) skip = false; else { // skip next comma, it's a surname separator skip = true; count = j - i; strncpy(garbage[countAuthors], i, count); garbage[countAuthors++][count] = '\0'; // advance past whitespace and comma for (i = j; *i != '\0' && *i != ':' && (*i == ',' || *i == ' '); ++i); j = i; if ('\0' == *j || ':' == *j) break; } } j++; } if (!skip) { // if we got a full name, it's our last one count = j - i; strncpy(garbage[countAuthors], i, count); garbage[countAuthors++][count] = '\0'; } // make sure we have all authors in the node list for (int k(0); k < countAuthors; ++k) npCache[k] = addNode(nodes, garbage[k]); // add links between all the authors on this paper for (int k(0); k < countAuthors; ++k) for (int l(0); l < countAuthors; ++l) { npCache[k]->addLink(npCache[l]); } } if (nodes.end() != nodes.find("Erdos, P.")) nodes["Erdos, P."]->erdosNumber = 0; while (queries--) { string line; getline(cin, line); cout << line << " "; int result(-1); hmsN::iterator i(nodes.find(line)); if (i != nodes.end()) { result = visit(queries, i->second, 0); // cache result if (-1 != result) i->second->erdosNumber = result; } if (-1 == result) cout << "infinity"; else cout << result; cout << endl; } } return 0; }