#pragma GCC optimize "O3" #include using namespace std; using LL=long long; #define FOR(i,l,r) for(int i=(l);i<=(r);++i) #define REP(i,n) FOR(i,0,(n)-1) #define ssize(x) int(x.size()) #ifdef DEBUG auto&operator<<(auto&o,pairp){return o<<"("<decltype(x.end(),o){o<<"{";int i=0;for(auto e:x)o<<","+!i++<sync_with_stdio(0); int n; cin >> n; vector> edges; vector in(n); REP(v, n) { cin >> in[v]; REP(u, n) { char c = in[v][u]; if(c == 'F' and v < u) edges.emplace_back(0, v, u); else if(c == 'S' and v < u) edges.emplace_back(1, v, u); } } REP(mask, 1 << n) { if(max(__builtin_popcount(mask), n - __builtin_popcount(mask)) <= (3 * n + 4 - 1) / 4 and 2 * min(__builtin_popcount(mask), n - __builtin_popcount(mask)) <= (3 * n + 4 - 1) / 4 and mask != 0 and mask != (1 << n) - 1) { debug(__builtin_popcount(mask), n - __builtin_popcount(mask)); int color_left = -1, color_mid = -1; auto is_valid = [&] { for(auto [c, v, u] : edges) if(((mask >> v) & 1) != ((mask >> u) & 1)) { if(color_mid == -1) color_mid = c; else if(color_mid != c) return false; } else if((mask >> v) & 1) { if(color_left == -1) color_left = c; else if(color_left != c) return false; } if(color_left != -1 and color_mid != -1 and color_left == color_mid) return false; return true; }; if(not is_valid()) continue; if(color_left == -1 and color_mid != -1) color_left = not color_mid; else if(color_left != -1 and color_mid == -1) color_mid = not color_left; else { color_left = 0; color_mid = 1; } assert(color_left != -1 and color_mid != -1 and color_left != color_mid); debug("found", mask); REP(v, n) REP(u, n) if(v != u and in[v][u] == '?') { if((mask >> v) & 1) in[v][u] = color_left ? 'S' : 'F'; else if(((mask >> v) & 1) != ((mask >> u) & 1)) in[v][u] = color_mid ? 'S' : 'F'; else in[v][u] = 'F'; } #ifdef LOCAL cout << "OK\n"; #else REP(i, n) cout << in[i] << '\n'; #endif exit(0); } } assert(false); }