每一单词相邻两个字母,不能同时为元音或者辅音。。。
各种姿势都可以过: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; }