codeforces Gym 100286J Javanese Cryptoanalysis (二染色)

每一单词相邻两个字母,不能同时为元音或者辅音。。。

各种姿势都可以过:7个for,dp,黑白染色,dfs,并查集。。。。

最主要的思路就是相邻字母连边,把元音和辅音看成两个集合,那么有连边的两个字母一定不能出现在同一个集合中,于是想到了二分图判断的二染色。

比较坑的是,必须要出现5个元音字母

见识到了str = str + str2有多慢

#include<bits/stdc++.h>
using namespace std;

#define PB push_back
int color[26];

int G[26][26];
const int maxn  = 1e5+5;
char s[maxn];
bool vis[26];

char mp[26];

bool bipartite(int u)
{
    for(int v = 0; v < 26; v++) if(G[u][v]) {
        if(color[v] == color[u]) return false;
        if(!color[v]){
            color[v] = 3 - color[u];
            if(!bipartite(v)) return false;
        }
    }
    return true;
}


char tab[5] = {'A','E','I','O','U'};
int tsz = 0,tsz2 = 0;
char tab2[21]  = {'B','C','D','F','G','H','J','K','L','M','N','P','Q','R','S','T','V','W','X','Y','Z'};

vector<string> word;
vector<int> bcc[26][2];
int bcnt;

bool dfs(int d,int cur,int s)
{
    if(d == bcnt){
        if(cur == 5){
            for(int i = 0; i < bcnt; i++){
               vector<int> &v = bcc[i][(s>>i)&1];
               for(int j = 0; j < v.size(); j++){
                    mp[v[j]] = tab[tsz++];
                }
            }
            return true;
        }
        return false;
    }
    if(dfs(d+1,cur+bcc[d][0].size(),s)||dfs(d+1,cur+bcc[d][1].size(),s|(1<<d))) return true;
    return false;
}

int main()
{
    //freopen("in.txt","r",stdin);
    freopen("javanese.in","r",stdin);
    freopen("javanese.out","w",stdout);
    while(~scanf("%s",s)){
        word.PB(s);
        for(int i = 1; s[i]; i++){
            int u = s[i] - 'A', v = s[i-1] - 'A';
            G[u][v] =  G[v][u] = 1;
        }
    }

    for(int i = 0; i < 26; i++)if(!color[i]){
        color[i] = 1;
        if(!bipartite(i)) { puts("impossible"); return 0; }
        for(int i = 0; i < 26; i++) if(color[i]&&!vis[i]) {
            vis[i] = true;
            bcc[bcnt][color[i]-1].PB(i);
        }
        bcnt++;
    }

    if(!dfs(0,0,0)) { puts("impossible"); }
    else {
        for(int i = 0; i < 26; i++) if(!mp[i]) mp[i] = tab2[tsz2++];
        for(int j = 0; j < word.size(); j++){
            if(j) putchar(' ');
            string & str = word[j];
            for(int i = 0; i < str.size(); i++){
                if('A'<=str[i]&&str[i]<='Z')
                   putchar(mp[str[i]-'A']);
                else putchar(str[i]);
            }
        }
        putchar('\n');
    }
    return 0;
}

 

posted @ 2015-08-08 21:44  陈瑞宇  阅读(355)  评论(0编辑  收藏  举报