計蒜客 A1594 封印之門 有向圖的全源最短路問題

題目描述

原題連接html

蒜頭君被暗黑軍團包圍在一座島上,全部通往近衛軍團的路都有暗黑軍團把手。幸運的是,小島上有一扇上古之神打造的封印之門,能夠通往近衛軍團,傳聞至今沒有人能解除封印。
封印之門上有一串文字,只包含小寫字母,有 k k k 種操做規則,每一個規則能夠把一個字符變換成另一個字符。通過任意屢次操做之後,最後若是能把封印之門上的文字變換成解開封印之門的文字,封印之門將會開啓。
蒜頭君戰鬥力超強,可是不擅計算,請你幫忙蒜頭君計算至少須要操做多少次才能解開封印之門。ios

輸入格式

輸入第一行一個字符串,長度不大於 10001000 10001000 10001000,只包含小寫字母,表示封印之門上的文字。
輸入第二行一個字符串,只包含小寫字母,保證長度和第一個字符串相等,表示能解開封印之門的文字。
輸入第三行一個整數 k ( 0 ≤ k ≤ 676 ) k(0≤k≤676) k(0k676)
接下來 k k k 行,每行輸出兩個空格隔開的字符 a a a, b b b,表示一次操做能把字符 a a a 變換成字符 b b bweb

輸出格式

若是蒜頭君能開啓封印之門,輸出最少的操做次數。不然輸出一行 − 1 −1 1svg

輸入樣例

abcd
dddd
3
a b
b c
c d

輸出樣例

6

分析

此題其實是一個全源最短路問題, 能看透題目的包裝, 就成功一半了
給出的變換規則,至關於有向圖中的有向邊
給出的兩個字符串, 至關於至關於有向圖中的頂點
求將字符串 1 1 1變爲字符串 2 2 2的最少的操做次數, 至關於求兩點間最短路徑
頂點的個數 k ( 0 ≤ k ≤ 676 ) k(0≤k≤676) k(0k676), 因此能夠用 Floyd來解決spa

注意:
1.圖爲有向圖.(爲何是有向圖? 每一個規則能夠把一個字符變換成另一個字符,因此是有向圖)
2.輸入數據中可能存在端點相同的數據(如 a   a a\ a a a),再存圖時須要忽略debug

實現

// 沒想到, 居然是最短路 Debug: 有向圖而不是無向圖
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
string str, p;
int k;
long long dis[29][29];
void init()
{
    for(int i=0; i<26; i++)
        for(int j=0; j<26; j++)
            if(i != j) dis[i][j] = INF;
}
int main()
{
    cin >> str >> p;
    cin >> k;
    init();
    for(int i=0; i<k; i++)
    {
        char a, b;
        cin >> a >> b;
        if(a==b) continue; // debug: 輸入數據中, 可能存在兩個端點相同
        dis[a-'a'][b-'a'] = 1;
    }
    for(int i=0; i<26; i++)
        for(int j=0; j<26; j++)
            for(int k=0; k<26; k++)
                dis[j][k] = min(dis[j][k], dis[j][i] + dis[i][k]);
    int sum = 0;
    for(int i = 0; i<str.size(); i++)
    {
        int val = dis[str[i]-'a'][p[i]-'a'];

        if(val >= INF) 
        {
            sum = -1;
            break;
        }
        sum += val;
    }
    cout << sum << endl;
    return 0;
}
相關文章
相關標籤/搜索