https://nanti.jisuanke.com/t/20692
封印之门
蒜头君被暗黑军团包围在一座岛上,所有通往近卫军团的路都有暗黑军团把手。幸运的是,小岛上有一扇上古之神打造的封印之门,可以通往近卫军团,传闻至今没有人能解除封印。
封印之门上有一串文字,只包含小写字母,有 kk 种操作规则,每个规则可以把一个字符变换成另外一个字符。经过任意多次操作以后,最后如果能把封印之门上的文字变换成解开封印之门的文字,封印之门将会开启。
蒜头君战斗力超强,但是不擅计算,请你帮忙蒜头君计算至少需要操作多少次才能解开封印之门。
输入格式
输入第一行一个字符串,长度不大于 10001000,只包含小写字母,表示封印之门上的文字。
输入第二行一个字符串,只包含小写字母,保证长度和第一个字符串相等,表示能解开封印之门的文字。
输入第三行一个整数 k(0 le k le 676)k(0≤k≤676)。
接下来 kk 行,每行输出两个空格隔开的字符 aa, bb,表示一次操作能把字符 aa 变换成字符 bb。
输出格式
如果蒜头君能开启封印之门,输出最少的操作次数。否则输出一行 -1−1。
样例输入
abcd
dddd
3
a b
b c
c d
样例输出
6
思路:开始一直以为就是一个简单的深搜,于是我用了邻接表去搜,但一直超时,最终看了大佬的代码发现竟然是一道考最短路的题。看到这句话赶紧回来写了一波,既然有可能匹配每一个,则要知道
每个点之间的距离,所以用弗洛伊德,同时存储路径时都减一个a化为整数去做。
#include <bits/stdc++.h> using namespace std; int mp[30][30]; int n = 28; const int INF = 0x3f3f3f3f; void floyd(){ for(int k = 0; k < n; k++){ for(int i = 0; i < n; i++){ for(int j = 0; j < n; j++){ if(mp[i][j] > mp[i][k] + mp[k][j]) mp[i][j] = mp[i][k] + mp[k][j]; } } } } int main(){ string str, mu; int m; cin >> str >> mu; cin >> m; memset(mp, INF, sizeof(mp)); for(int i = 0; i < m; i++){ char x, y; cin >> x >> y; mp[x - 'a'][y - 'a'] = 1; } floyd(); int ans = 0; for(int i = 0; i < str.length(); i++){ if(str[i] == mu[i]) continue; if(mp[str[i] - 'a'][mu[i] - 'a'] < INF) ans += mp[str[i] - 'a'][mu[i] - 'a']; else{ cout << -1 << endl; continue; } } cout << ans << endl; return 0; }