/* 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";
}
|