/* Topcoder SRM 705, D2 500-Pointer. AlphabetOrderDiv2 James S. Plank Wed Oct 6 14:05:31 EDT 2021 */ #include <string> #include <vector> #include <iostream> #include <cstdio> #include <cstdlib> using namespace std; class AlphabetOrderDiv2 { public: string isOrdered(vector <string> words); }; string AlphabetOrderDiv2::isOrdered(vector <string> words) { int i, j, c1, c2; vector < vector <int> > Adj; vector <int> nincident; vector <int> inc_nodes; /* Create an adjacency matrix from all of the words. You should make sure that you don't set an edge from a node to itself. */ Adj.resize(26); for (i = 0; i < Adj.size(); i++) Adj[i].resize(26, 0); for (i = 0; i < words.size(); i++) { for (j = 1; j < words[i].size(); j++) { c1 = words[i][j-1] - 'a'; c2 = words[i][j] - 'a'; if (c1 != c2) Adj[c1][c2] = 1; } } /* Print the adjacency matrix. */ // printf(" "); // for (i = 'a'; i <= 'z'; i++) printf("%c", i); // printf("\n"); // for (i = 0; i < Adj.size(); i++) { // printf("%c ", 'a'+i); // for (j = 0; j < Adj.size(); j++) printf("%d", Adj[i][j]); // printf("\n"); // } /* For each edge in the adjacency matrix, add one to the number of incident edges for each node. */ nincident.resize(Adj.size(), 0); for (i = 0; i < Adj.size(); i++) { for (j = 0; j < Adj[i].size(); j++) { if (Adj[i][j]) nincident[j]++; } } /* Now make a vector of all of the nodes with no incident edges: */ for (i = 0; i < nincident.size(); i++) if (nincident[i] == 0) inc_nodes.push_back(i); /* Do the topological sort -- run through inc_nodes and decrement nincident for each node incident to the node in question. If that becomes zero, push it back onto inc_nodes. */ for (i = 0; i < inc_nodes.size(); i++) { c1 = inc_nodes[i]; for (j = 0; j < Adj[c1].size(); j++) { if (Adj[c1][j] == 1) { nincident[j]--; if (nincident[j] == 0) inc_nodes.push_back(j); } } } /* If all of the nodes now have 0 incident edges, the graph was acyclic. There are 26 nodes, so simply check whether inc_nodes.size() is 26. */ return (inc_nodes.size() == 26) ? "Possible" : "Impossible"; } |