結果

問題 No.470 Inverse S+T Problem
ユーザー maimai
提出日時 2016-12-29 23:53:41
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
WA  
実行時間 -
コード長 7,380 bytes
コンパイル時間 1,812 ms
コンパイル使用メモリ 182,408 KB
実行使用メモリ 4,380 KB
最終ジャッジ日時 2023-08-24 01:26:14
合計ジャッジ時間 3,482 ms
ジャッジサーバーID
(参考情報)
judge11 / judge12
このコードへのチャレンジ(β)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
4,376 KB
testcase_01 AC 1 ms
4,380 KB
testcase_02 AC 2 ms
4,380 KB
testcase_03 WA -
testcase_04 AC 1 ms
4,376 KB
testcase_05 AC 1 ms
4,376 KB
testcase_06 AC 1 ms
4,380 KB
testcase_07 AC 1 ms
4,376 KB
testcase_08 AC 1 ms
4,380 KB
testcase_09 WA -
testcase_10 WA -
testcase_11 WA -
testcase_12 WA -
testcase_13 WA -
testcase_14 WA -
testcase_15 AC 2 ms
4,376 KB
testcase_16 WA -
testcase_17 WA -
testcase_18 WA -
testcase_19 AC 2 ms
4,380 KB
testcase_20 AC 1 ms
4,376 KB
testcase_21 AC 1 ms
4,380 KB
testcase_22 AC 1 ms
4,376 KB
testcase_23 AC 2 ms
4,376 KB
testcase_24 AC 1 ms
4,376 KB
testcase_25 WA -
testcase_26 AC 1 ms
4,380 KB
testcase_27 AC 1 ms
4,376 KB
testcase_28 AC 2 ms
4,376 KB
testcase_29 AC 2 ms
4,380 KB
testcase_30 AC 1 ms
4,380 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include<bits/stdc++.h>

using namespace std;
typedef unsigned int uint;
typedef long long int ll;
typedef unsigned long long int ull;

#define debugv(v) printf("L%d %s => ",__LINE__,#v);for(auto e:v){cout<<e<<" ";}cout<<endl;
#define debugm(m) printf("L%d %s is..\n",__LINE__,#m);for(auto v:m){for(auto e:v){cout<<e<<" ";}cout<<endl;}
#define debuga(m,w) printf("L%d %s is => ",__LINE__,#m);for(int x=0;x<(w);x++){cout<<(m)[x]<<" ";}cout<<endl;
#define debugaa(m,w,h) printf("L%d %s is..\n",__LINE__,#m);for(int y=0;y<(h);y++){for(int x=0;x<(w);x++){cout<<(m)[x][y]<<" ";}cout<<endl;}
#define debugaar(m,w,h) printf("L%d %s is..\n",__LINE__,#m);for(int y=0;y<(h);y++){for(int x=0;x<(w);x++){cout<<(m)[y][x]<<" ";}cout<<endl;}
#define ALL(v) (v).begin(),(v).end()
#define BIGINT 0x7FFFFFFF
#define E107 1000000007ll
void printbit(int u){if(u==0)cout<<0;else{int s=0,k=0;for(;0<u;u>>=1,k++)s=(s<<1)|(u&1);for(;0<k--;s>>=1)cout<<(s&1);}}

#define TIME chrono::system_clock::now()
#define MILLISEC(t) (chrono::duration_cast<chrono::milliseconds>(t).count())

template<typename T1,typename T2>
ostream& operator <<(ostream &o,const pair<T1,T2> p){o<<"("<<p.first<<":"<<p.second<<")";return o;}

class Graph{
public:
    const size_t n;
    vector<vector<int>> vertex_to;   // vector<set<int>>でも良いかもしれない?
    vector<vector<int>> vertex_from;
    
    Graph(size_t n):n(n),vertex_to(n),vertex_from(n){}
    
    void connect(int from, int to){
        vertex_to[from].emplace_back(to);
        vertex_from[to].emplace_back(from);
    }
    vector<int>& operator[](int v){
        return vertex_to[v];
    }
    void resize(size_t n){
        vertex_to.resize(n);
        vertex_from.resize(n);
    }

    size_t degree(int v){
        return vertex_to[v].size() + vertex_from[v].size();
    }
    size_t degree_in(int v){
        return vertex_from[v].size();
    }
    size_t degree_out(int v){
        return vertex_to[v].size();
    }
    void reverse_direction(){
        vertex_from.swap(vertex_to);
    }
};

class unionfind {
public:
    vector<int> data;
    unionfind(int size) : data(size, -1) { }
    bool union_set(int x, int y) {
        x = root(x); y = root(y);
        if (x != y) {
            if (data[y] < data[x]) swap(x, y);
            data[x] += data[y]; data[y] = x;
        }
        return x != y;
    }
    bool find_set(int x, int y) {
        return root(x) == root(y);
    }
    int root(int x) {
        return data[x] < 0 ? x : data[x] = root(data[x]);
    }
    int size(int x) {
        return -data[root(x)];
    }
};

// http://www.prefield.com/algorithm/graph/strongly_connected_components.html
template <typename U_FIND>
void strongly_connected_components_dfs(const Graph &g, int v, U_FIND& result,
    stack<int> &s, vector<bool> &flg,
    vector<int> &low, vector<int> &num, int& count) {
    
    low[v] = num[v] = count++;
    s.push(v);
    flg[v] = true;
    
    for (int w : g.vertex_to[v]){
        if (num[w] == 0) {
            strongly_connected_components_dfs(g, w, result, s, flg, low, num, count);
            low[v] = min(low[v], low[w]);
        } else if (flg[w]){ // ?
            low[v] = min(low[v], num[w]);
        }
    }
    if (low[v] == num[v]) {
        while (!s.empty()) {
            int w = s.top(); s.pop();
            flg[w] = false;
            if (v == w) break;
            result.union_set(v,w);
        }
    }
}
template <typename U_FIND>
void strongly_connected_components(const Graph& graph, U_FIND& result) {
    int size = graph.n;
    vector<int> num(size), low(size);
    stack<int> s;
    vector<bool> flg(size);
    int count = 1;
    for (int i=0; i<graph.n; i++){
        if (num[i] == 0){
            strongly_connected_components_dfs(graph,i,result,s,flg,low,num,count);
        }
    }
}

class sat_2{
public:
    size_t n;
    Graph graph;
    
    sat_2(size_t n):n(n),graph(n*2+1){
    }
    
private:
    int _cv(int v){return 0<v ? v : -v+n;}
    int _rv(int v){return v<n ? v : -v+n;}
    
    // http://www.prefield.com/algorithm/misc/2-sat.html
    void _scc_dfs(int v, vector<int>& ord, vector<int> &num, int k){
        if (0 <= num[v]) return;
        num[v] = k;
        for (int to : graph.vertex_to[v])
            _scc_dfs(to, ord, num, k);
        ord.push_back(v);
    }
public:
    
    // 1 <= a <= n OR -1 >= a >= -n
    // 正ならばx_a,負ならばNOT x_aを表現.
    void emplace(int a,int b){
        // assert(a!=0 && b!=0);
        graph.connect(_cv(-a),_cv(b));
        graph.connect(_cv(-b),_cv(a));
    }
    
    // TODO:殆どコピペなので読み直し
    bool solve(vector<bool>& result){
        int i;
        vector<int> num(graph.n, -1), ord, dro;
        
        for (i=0; i<graph.n; i++)
            _scc_dfs(i, ord, num, i);
            
        reverse(ord.begin(), ord.end());
        graph.reverse_direction();
        fill(num.begin(), num.end(), -1);
        
        for (i=0; i<graph.n; i++)
            _scc_dfs(ord[i], dro, num, i);
        for (i=1; i<=n; i++)
            if (num[i] == num[i+n])
                return false;
        
        result.resize(n+1);
        for (i=1; i<=n; i++){
            result[i] = (num[i] < num[i+n]);
        }
        
        graph.reverse_direction(); // 戻しておく
        return true;
    }
    
    // strongly_connected_components使ってる感を醸し出せるので
    // 消さずに残しておく
    bool satisfied(){
        unionfind uf(graph.n);
        strongly_connected_components(graph,uf);
        
        for (int i=1;i<=n;i++){
            if (uf.find_set(i,i+n)){
                return false;
            }
        }
        return true;
    }
    
};

int width,height;
int m,n;

string data[100];

void halt(){
    cout << "Impossible" << endl;
    exit(0);
}

bool check(int i,int j,int bit){
    switch(bit){
    case 0:
        if (data[i][0]==data[j][0] && data[i][1]==data[j][1]) return false;
        if (data[i][2]==data[j][2]) return false;
        return true;
    case 1:
        if (data[i][1]==data[j][0] && data[i][2]==data[j][1]) return false;
        if (data[i][0]==data[j][2]) return false;
        return true;
    case 2:
        if (data[i][0]==data[j][1] && data[i][1]==data[j][2]) return false;
        if (data[i][2]==data[j][0]) return false;
        return true;
    case 3:
        if (data[i][1]==data[j][1] && data[i][2]==data[j][2]) return false;
        if (data[i][0]==data[j][0]) return false;
        return true;
    }
    abort();
}

int main(){
    int i,j,k;
    int x,y,a,b;
    
    cin >> n;
    if (52 < n) halt();
    
    cin.ignore();
    for (i=1;i<=n;i++){
        cin >> data[i];
    }
    
    sat_2 sat(n);
    for (i=1;i<=n-1;i++){
        for (j=i+1;j<=n;j++){
            if (!check(i,j,0b00))
                sat.emplace(i,j);
            if (!check(i,j,0b01))
                sat.emplace(i,-j);
            if (!check(i,j,0b10))
                sat.emplace(-i,j);
            if (!check(i,j,0b11))
                sat.emplace(-i,-j);
        }
    }
    vector<bool> result;
    if (!sat.solve(result)) halt();
    
    for (i=1;i<=n;i++){
        //cout << result[i];
        if (result[i]){
            printf("%c %c%c\n",data[i][0],data[i][1],data[i][2]);
        }else{
            printf("%c%c %c\n",data[i][0],data[i][1],data[i][2]);
        }
    }
    
    
    return 0;
}
0