字符串最短路。假设输入两字符串 $s,\,t$。如果 $s$ 和 $t$ 长度不同则一定不能转换,输出 $-1$。
随后首先使用 Floyd 算法计算出将每个字母转换成每个字母的最小代价,若无法转换则代价为 $+infty$。随后枚举 $s$ 和 $t$ 每个相同位置转换为相同字符的最小代价,若为 $+infty$ 则输出 $-1$,否则 $ ext{sum}$ 加上这个最小代价,将字符串 $s$ 当前位置改为这个字符。
此题有两个坑点:
- 输入中可能有重边,需要取最小而不是直接赋值。好在 CF 出题人良心,样例 $2$ 就是这种情况,若不判断是过不了的。
- 对于 $s_i$ 和 $t_i$,不一定只有将 $s_i$ 变为 $t_i$ 和将 $t_i$ 变为 $s_i$ 才是最值,需要枚举每个字母,计算最小值。
$ ext{Code}$:
1 const int N = 30; 2 const int inf = 0x3f3f3f3f; 3 4 int m, sum; 5 string s, t; 6 int trans[N][N]; 7 8 int main() { 9 memset(trans, 0x3f, sizeof trans); 10 cin >> s >> t >> m; 11 if(s.size() != t.size()) return puts("-1"), 0; 12 while(m--) { 13 char c, cc; 14 int d; 15 scanf(" %c %c", &c, &cc); 16 scanf("%d", &d); 17 To_min(trans[c - 'a' + 1][cc - 'a' + 1], d); 18 } 19 rep(i, 1, 26) trans[i][i] = 0; 20 rep(k, 1, 26) { 21 rep(i, 1, 26) { 22 rep(j, 1, 26) { 23 To_min(trans[i][j], trans[i][k] + trans[k][j]); 24 } 25 } 26 } 27 rep(i, 0, s.size() - 1) { 28 int ss = s[i] - 'a' + 1, tt = t[i] - 'a' + 1; 29 int mn = inf, f; 30 rep(j, 1, 26) { 31 if(mn > trans[ss][j] + trans[tt][j]) mn = trans[ss][j] + trans[tt][j], f = j; 32 } 33 if(mn == inf) return puts("-1"), 0; 34 sum += mn, s[i] = char(f - 1 + 'a'); 35 } 36 cout << sum << endl << s << endl; 37 return 0; 38 }