#include using namespace std; using ll = long long; #define rep(i, n) for (int i = 0; i < (int)(n); ++i) #define all(c) begin(c), end(c) #define dump(x) cerr << __LINE__ << ":\t" #x " = " << (x) << endl using Weight = int; using Cap = int; struct Edge { int src, dst; Cap cap; Edge(int s, int d, Cap c) : src(s), dst(d), cap(c) {} }; using Edges = vector; using Graph = vector; using Array = vector; using Matrix = vector; struct dinic { int n, s, t; vector level, prog, que; vector> cap, flow; vector> g; Cap inf; dinic(const Graph &graph) : n(graph.size()), cap(n, vector(n)), flow(n, vector(n)), g(n, vector()), inf(numeric_limits::max() / 8) { for (int i = 0; i < n; i++) { for (auto &e : graph[i]) { int u = e.src, v = e.dst; Cap c = e.cap; cap[u][v] += c; cap[v][u] += c; flow[v][u] += c; g[u].push_back(v); g[v].push_back(u); } } } inline Cap residue(int u, int v) { return cap[u][v] - flow[u][v]; } Cap solve(int s_, int t_) { this->t = t_, this->s = s_; que.resize(n + 1); Cap res = 0; while (levelize()) { prog.assign(n, 0); res += augment(s, inf); } return res; } bool levelize() { int l = 0, r = 0; level.assign(n, -1); level[s] = 0; que[r++] = s; while (l != r) { int v = que[l++]; if (v == t) break; for (const int &d : g[v]) if (level[d] == -1 && residue(v, d) != 0) { level[d] = level[v] + 1; que[r++] = d; } } return level[t] != -1; } Cap augment(int v, Cap lim) { Cap res = 0; if (v == t) return lim; for (int &i = prog[v]; i < (int)g[v].size(); i++) { const int &d = g[v][i]; if (residue(v, d) == 0 || level[v] >= level[d]) continue; const Cap aug = augment(d, min(lim, residue(v, d))); flow[v][d] += aug; flow[d][v] -= aug; res += aug; lim -= aug; if (lim == 0) break; } return res; } }; int main() { vector alpha; for (char c = 'A'; c <= 'Z'; ++c) { alpha.push_back(c); } for (char c = 'a'; c <= 'z'; ++c) { alpha.push_back(c); } vector vs; for (char c : alpha) { string s = { c }; vs.push_back(s); for (char d : alpha) { string t = { c, d }; vs.push_back(t); } } sort(vs.begin(), vs.end()); auto id = [&](const string &s) { return lower_bound(all(vs), s) - vs.begin(); }; int n; while (cin >> n) { int N = vs.size() * 2 + vs.size() + 2; int S = N - 2; int T = N - 1; Graph g(N); // S->(1->2)*->T for (auto &v : vs) { if (v.size() == 1) { int i = id(v); g[S].emplace_back(S, i, 1); } else { int i = id(v); g[i].emplace_back(i, T, 1); } } vector ss(n); for (int i = 0; i < n; i++) { string &s = ss[i]; cin >> s; string a = s.substr(0, 1); string ab = s.substr(0, 2); string bc = s.substr(1, 2); string c = s.substr(2, 1); g[id(a)].emplace_back(id(a), id(bc), 1); g[id(c)].emplace_back(id(c), id(ab), 1); } dinic dn(g); int f = dn.solve(S, T); if (f >= n) { // cout << "possible" << endl; for (auto &s : ss) { string a = s.substr(0, 1); string bc = s.substr(1); int ia = id(a); int ibc = id(bc); string ab = s.substr(0, 2); string c = s.substr(2); int iab = id(ab); int ic = id(c); if (dn.flow[ia][ibc]) { cout << a << ' ' << bc << '\n'; dn.flow[ia][ibc] = 0; } else if(dn.flow[ic][iab]){ cout << ab << ' ' << c << '\n'; dn.flow[ic][iab] = 0; } } } else { cout << "Impossible" << '\n'; } } }