题意:
有n个只包含两个字母的字符串, 要求构造一个m*m的字母矩阵, 使得矩阵的每行每列都不包含所给的字符串, m要尽量大, 如果大于20的话构造20*20的矩阵就行了。
思路:
对每个字符串第一个字母连向第二个字母一条有向边, 然后取它的补图。
在补图上,如果有环的话, 取环上的字母就一定可以构造上20*20的矩阵, 如果没环的话矩阵一定是用最长路来构造,假设最长路长度为len, 则矩阵大小为(len+1)/2。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <stack>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <ctime>
#include <cstdlib>
using namespace std;
#define mxn 30
#define mxe 900
#define mod 10000007
#define LL long long
#define inf 0x3f3f3f3f
#define vi vector<int>
#define PB push_back
#define MP make_pair
#define pii pair<int, int>
#define G(i, u) for(int i = fst[u]; ~i; i = nxt[i])
#define F(i, n) for(int i = 1; i <= n; ++i)
#pragma comment(linker,"/STACK:1024000000,1024000000")
#define ls (i << 1)
#define rs (ls | 1)
#define md ((ll + rr) >> 1)
bool g[mxn][mxn];
int pre[mxn];
int n;
char ans[mxn][mxn];
int dp[mxn];
bool bfs(int s) {
queue<int> q;
q.push(s);
memset(pre, -1, sizeof pre);
while(!q.empty()) {
int u = q.front(); q.pop();
for(int i = 0; i < n; ++i) {
if(g[u][i] == 0) continue;
int v = i;
if(v == s) {
pre[s] = u;
return 1;
}
if(pre[v] == -1) {
pre[v] = u;
q.push(v);
}
}
}
return 0;
}
int dfs(int u) {
if(dp[u] != -1) return dp[u];
dp[u] = 1;
for(int i = 0; i < n; ++i) {
if(g[i][u] == 0) continue;
int tmp = dfs(i) + 1;
if(tmp + 1 > dp[u])
dp[u] = tmp + 1, pre[u] = i;
}
return dp[u];
}
int main() {
// freopen("tt.txt", "r", stdin);
int cas;
scanf("%d", &cas);
n = 26;
while(cas--) {
memset(g, 1, sizeof g);
int t;
scanf("%d", &t);
if(t == 0) {
for(int i = 0; i < 20; ++i)
for(int j = 0; j < 20; ++j) {
printf("%c", 'a');
if(j == 19)
puts("");
}
continue;
}
while(t--) {
char s[3];
scanf("%s", s);
g[s[0]-'a'][s[1]-'a'] = 0;
}
int lp = -1;
for(int i = 0; i < n; ++i) {
if(bfs(i)) {
lp = i;
break;
}
}
// printf("%d\n", lp);
if(lp != -1) {
int cnt = 0;
char s[30];
for(int i = pre[lp]; i != lp; i = pre[i]) {
s[cnt++] = i + 'a';
}
s[cnt++] = lp + 'a';
reverse(s, s + cnt);
s[cnt] = '\0';
// puts(s);
for(int i = 0; i < 20; ++i) {
for(int j = 0; j < 20; ++j)
ans[i][j] = s[(i+j)%cnt];
ans[i][20] = '\0';
}
for(int i = 0; i < 20; ++i)
printf("%s\n", ans[i]);
continue;
}
memset(dp, -1, sizeof dp);
memset(pre, -1, sizeof pre);
int id = -1;
for(int i = 0; i < 26; ++i) {
int tmp = dfs(i);
if(id == -1 || tmp > dp[id])
id = i;
}
char s[mxn];
int cnt = 0;
for(int i = id; i != -1; i = pre[i])
s[cnt++] = i + 'a';
reverse(s, s + cnt);
if(cnt % 2 == 0)
--cnt;
int len = (cnt + 1) / 2;
for(int i = 0; i < len; ++i) {
for(int j = 0; j < len; ++j)
ans[i][j] = s[(i+j)%cnt];
ans[i][len] = '\0';
printf("%s\n", ans[i]);
}
}
return 0;
}