|
|
#include <bits/stdc++.h>
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
const int N = 1e3 + 10;
|
|
|
const int M = 1e5 + 10;
|
|
|
const int U = 26 * 26;
|
|
|
|
|
|
int n;
|
|
|
int h[N], e[M], w[M], ne[M], idx;
|
|
|
double dist[N];
|
|
|
bool st[N]; // 如果当前这个点 u 可以松弛的点 v 是被访问过的,那么就说明一定存在负环。
|
|
|
char str[N]; // 黄海替换为string,结果执行时间由70ms--> 400ms!!!
|
|
|
|
|
|
const double eps = 1e-3;
|
|
|
|
|
|
void add(int a, int b, int c) {
|
|
|
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
|
|
|
}
|
|
|
|
|
|
bool dfs(int u, double mid) {
|
|
|
if (st[u]) return 1; // 如果又见u,说明有环
|
|
|
bool flag = 0; // 我的后代们是不是有环?
|
|
|
st[u] = 1; // u我出现过一次了~
|
|
|
for (int i = h[u]; ~i; i = ne[i]) {
|
|
|
int v = e[i];
|
|
|
// 更新最小值,判负环
|
|
|
if (dist[v] > dist[u] - w[i] + mid) {
|
|
|
dist[v] = dist[u] - w[i] + mid;
|
|
|
// 检查一下我的下一个节点j,它要是有负环检查到,我也汇报
|
|
|
flag = dfs(v, mid);
|
|
|
if (flag) break;
|
|
|
}
|
|
|
}
|
|
|
st[u] = 0; // 回溯
|
|
|
return flag;
|
|
|
}
|
|
|
|
|
|
bool check(double mid) {
|
|
|
memset(dist, 0, sizeof dist);
|
|
|
for (int i = 0; i < U; i++)
|
|
|
if (dfs(i, mid)) return 1;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
void solve() {
|
|
|
memset(h, -1, sizeof h);
|
|
|
idx = 0;
|
|
|
|
|
|
while (n--) {
|
|
|
scanf("%s", str);
|
|
|
int len = strlen(str);
|
|
|
if (len < 2) continue;
|
|
|
int a = (str[0] - 'a') * 26 + str[1] - 'a';
|
|
|
int b = (str[len - 2] - 'a') * 26 + str[len - 1] - 'a';
|
|
|
add(a, b, len);
|
|
|
}
|
|
|
|
|
|
double l = 0, r = 1e3;
|
|
|
while (r - l > eps) {
|
|
|
double mid = (l + r) / 2;
|
|
|
if (check(mid))
|
|
|
l = mid;
|
|
|
else
|
|
|
r = mid;
|
|
|
}
|
|
|
if (l < eps)
|
|
|
puts("No solution");
|
|
|
else
|
|
|
printf("%.2lf\n", r);
|
|
|
}
|
|
|
|
|
|
int main() {
|
|
|
// 多组测试数组,喜欢单开一个solve()进行处理,确实看着舒服
|
|
|
while (scanf("%d", &n), n) solve();
|
|
|
return 0;
|
|
|
} |