#include #include using namespace std; // 強連結成分分解: Strongly Connected Components class SCC { int n; int scc_num; vector> fG, rG; vector used; vector order; // 属する強連結成分のトポロジカル順序 vector vertices; // 帰りがけ順の並び void dfs(int u); void rdfs(int v, int k); public: SCC(int n); void add_edge(int u, int v); // u から v に辺を張る void solve(); vector get_order(); vector> restore_sccs(); // solve() の後に呼び出して強連結成分をトポロジカル順序で返す }; SCC::SCC(int n) : n(n) { fG.assign(n, vector()); rG.assign(n, vector()); } void SCC::add_edge(int u, int v) { fG[u].push_back(v); rG[v].push_back(u); } void SCC::dfs(int u) { used[u] = true; for(int v : fG[u]) { if(!used[v]) { dfs(v); } } vertices.push_back(u); } void SCC::rdfs(int v, int k) { used[v] = true; order[v] = k; for(int u : rG[v]) { if(!used[u]) { rdfs(u, k); } } } vector SCC::get_order() { return order; } void SCC::solve() { used.assign(n, false); order.assign(n, 0); vertices.clear(); for(int u=0; u=0; --i) { if(!used[vertices[i]]) { rdfs(vertices[i], scc_num++); } } } vector> SCC::restore_sccs() { vector> res(scc_num, vector()); // res[scc_num][] for(int i=0; i solve(); // 戻り値: 可能なら真偽の割り当て、不可能なら空配列 }; TwoSAT::TwoSAT(int n) : n(n), g(2*n) {} void TwoSAT::add_clause(bool flag0, int x0, bool flag1, int x1) { g.add_edge(x0 + n * !flag0, x1 + n * flag1); // !x0 => x1 g.add_edge(x1 + n * !flag1, x0 + n * flag0); // !x1 => x0 // メモ: (x0 | x1) = (!x0 => x1 & !x1 => x0) } vector TwoSAT::solve() { g.solve(); vector order = g.get_order(); vector res(n); for(int i=0; i(); } // 充足不可能 if(order[i] > order[i+n]) { res[i] = true; } } return res; } int main(void) { cin.tie(0); ios::sync_with_stdio(false); int n; cin >> n; if(n > 60) { cout << "Impossible\n"; return 0; } vector u(n); for(int i=0; i> u[i]; } TwoSAT sat(n); string s1, s2, t1, t2; for(int i=0; i res = sat.solve(); if(!res.size()) { cout << "Impossible\n"; return 0; } for(int i=0; i