You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

77 lines
2.0 KiB

2 years ago
#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;
}