#include #include #include #include #include #define repeat(i,n) for (int i = 0; (i) < int(n); ++(i)) #define repeat_from(i,m,n) for (int i = (m); (i) < int(n); ++(i)) using namespace std; struct strongly_connected_components { static pair > decompose(vector > const & g) { // adjacent list strongly_connected_components scc(g); return { scc.k, scc.c }; } private: int n; vector > to, from; explicit strongly_connected_components(vector > const & g) : n(g.size()), to(g), from(n) { repeat (i,n) for (int j : to[i]) from[j].push_back(i); decompose(); } vector used; vector vs; void dfs(int i) { used[i] = true; for (int j : to[i]) if (not used[j]) dfs(j); vs.push_back(i); } int k; // number of scc vector c; // i-th vertex in g is in c_i-th vertex in scc-decomposed g void rdfs(int i) { used[i] = true; c[i] = k; for (int j : from[i]) if (not used[j]) rdfs(j); } void decompose() { used.clear(); used.resize(n, false); repeat (i,n) if (not used[i]) dfs(i); used.clear(); used.resize(n, false); k = 0; c.resize(n); reverse(vs.begin(), vs.end()); for (int i : vs) if (not used[i]) { rdfs(i); k += 1; } } }; vector twosat(int n, vector > const & cnf) { vector > g(2*n); auto i = [&](int x) { assert (x != 0 and abs(x) <= n); return x > 0 ? x-1 : n-x-1; }; for (auto it : cnf) { int x, y; tie(x, y) = it; // x or y g[i(- x)].push_back(i(y)); // not x implies y g[i(- y)].push_back(i(x)); // not y implies x } vector component = strongly_connected_components::decompose(g).second; vector valuation(n); repeat_from (x,1,n+1) { if (component[i(x)] == component[i(- x)]) { // x iff not x return vector(); // unsat } valuation[x-1] = component[i(x)] > component[i(- x)]; // use components which indices are large } return valuation; } int main() { int n; cin >> n; vector s(n); repeat (i,n) cin >> s[i]; assert (1 <= n and n <= 100000); repeat (i,n) assert (s[i].length() == 3); vector result; if (n <= (26*2)*(26*2+1)) { // x_i : U_i = S + TT // not x_i : U_i = SS + T vector > cnf; map > used; repeat (i,n) { int x = i + 1; used[s[i].substr(0, 1)].push_back(+ x); used[s[i].substr(1, 2)].push_back(+ x); used[s[i].substr(0, 2)].push_back(- x); used[s[i].substr(2, 1)].push_back(- x); } for (auto it : used) { for (int x : it.second) for (int y : it.second) if (x < y) { // cerr << "not " << x << " or " << "not " << y << endl; cnf.emplace_back(- x, - y); // not x or not y } } result = twosat(n, cnf); } if (result.empty()) { cout << "Impossible" << endl; } else { repeat (i,n) { if (result[i]) { cout << s[i][0] << ' ' << s[i][1] << s[i][2] << endl; } else { cout << s[i][0] << s[i][1] << ' ' << s[i][2] << endl; } } } return 0; }