Codeforces 33B String Problem (Floyd字符串最短路)

首先看一下题面:

Boy Valera likes strings. And even more he likes them, when they are identical. That's why in his spare time Valera plays the following game. He takes any two strings, consisting of lower case Latin letters, and tries to make them identical. According to the game rules, with each move Valera can change one arbitrary character Ai in one of the strings into arbitrary character Bi, but he has to pay for every move a particular sum of money, equal to Wi. He is allowed to make as many moves as he needs. Since Valera is a very economical boy and never wastes his money, he asked you, an experienced programmer, to help him answer the question: what minimum amount of money should Valera have to get identical strings.

Input

The first input line contains two initial non-empty strings s and t, consisting of lower case Latin letters. The length of each string doesn't exceed 105. The following line contains integer n (0 ≤ n ≤ 500) — amount of possible changings. Then follow n lines, each containing characters Ai and Bi (lower case Latin letters) and integer Wi (0 ≤ Wi ≤ 100), saying that it's allowed to change character Ai into character Bi in any of the strings and spend sum of money Wi.

Output

If the answer exists, output the answer to the problem, and the resulting string. Otherwise output -1 in the only line. If the answer is not unique, output any.

Examples

input

Copy

uayd
uxxd
3
a x 8
x y 13
d c 3

output

Copy

21
uxyd

input

Copy

a
b
3
a b 2
a b 3
b a 5

output

Copy

2
b

input

Copy

abc
ab
6
a b 4
a b 7
b a 8
c b 11
c a 3
a c 0

output

Copy

-1

大致题意就是用最小的代价通过已知的路子把两个字符串变成一样的字符串,由于这是双源最短路,所以dijkstra是不可用的。

我们采用基于动态规划的floyd算法,详细的会在代码注释中给出。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <iomanip>
#include <cstring>
#include <cmath>
//#include <minmax.h>
#define DETERMINATION main
#define lldin(a) scanf("%lld",&a)
#define din(a) scanf("%d",&a)
#define reset(a,b) memset(a,b,sizeof(a))
const int INF=0x3f3f3f3f;
using namespace std;
typedef long long ll;
/*you can feel the pulse of your destiny...
The nervous feeling fills you with determination.*/
char s[100007],t[100007];//这是两个字符串数组。
char finally[100007];//这是用来存储最后变成的字符串的数组。
int dp[501][501],convert[501][501];//动态规划数组,以及记录两个字母与同时转变为哪个字母的数组
int anses[501][501];//暂时记录每一步花费的数组
bool visited[501][501];//标记数组
int sign=0;
int solve(int x,int y)
{
     if(visited[x][y])//如果这对点的组合已经计算过了
       return anses[x][y];//直接返回之前存储的子问题答案
     visited[x][y]=visited[y][x]=1;
     int tmp4=INF,tmp5;
     for(int i=1;i<=26;i++)//枚举两者要变换成的字母
     {
        if(tmp4>dp[x][i]+dp[y][i])
        {
            tmp4=dp[x][i]+dp[y][i];
            tmp5=i;//记下这个字母
        }
     }
     if(tmp4==INF)
        sign=1;//若TMP4没有被更新,则[x][y]两个字母没有可做的变换
     convert[x][y]=convert[y][x]=tmp5;//记录下变换后的字母数字代号
     return anses[x][y]=anses[y][x]=tmp4;//把花费同样记录下
}
int DETERMINATION()
{
    cin>>s>>t;
    int n;
    cin>>n;
    for(int i=1; i<=26; i++)//必要的初始化,1-26指代26个字母
        for(int j=1; j<=26; j++)
        {
            if(i==j)//若两个字母相等
            {
                visited[i][j]=1//没必要再访问它了,anses[i][j]=j//假定它的成本为j;
            }
            else//若两个字母不等
            {
                dp[i][j]=INF,anses[i][j]=INF,convert[i][j]=0;
                //初始化最短路,成本花费为无穷大,两者转变为的字母为0;
            }
        }
    char tmp1,tmp2;
    int value;
    cin.get();
    //防止换行符干扰
    for(int i=1; i<=n; i++)
    {
        cin>>tmp1>>tmp2>>value;
        tmp1=tmp1-'a'+1;
        tmp2=tmp2-'a'+1;
        dp[(int)tmp1][(int)tmp2]=min(value,dp[int(tmp1)][int(tmp2)]);
        //由于题目中可能给出多条路线,所以必须选择其中花费最小的一种。
        cin.get();//防止换行符干扰
    }
    int len1=strlen(s),len2=strlen(t);
    if(len1!=len2)//若两个字符串长度不等,那么再怎么变换也是没有用的。
     cout<<-1<<endl;
    else
    {
       for(int k=1;k<=26;k++)//中间隔着点K
         for(int i=1;i<=26;i++)//出发点
           for(int j=1;j<=26;j++)//终点
        {
           dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);
           //可以看做向量ij和向量(ik+kj)之间的大小关系
        }
      int ans=0,tmp3;
      for(int i=0;i<len1;i++)
      {
          char ch1=s[i];
          char ch2=t[i];
          if(ch1==ch2)
           finally[i]=ch1;//如果相等,把它存入finally数组中
            else
            {
                int x=s[i]-'a'+1;
                int y=t[i]-'a'+1;//变为数字处理
                tmp3=solve(x,y);
                if(sign)
                 {
                  cout<<-1<<endl;
                  break;
                }
                ans+=tmp3;
                finally[i]=convert[x][y]+'a'-1;//变回字母
            }
      }
      if(!sign)
      {
      cout<<ans<<endl;
      cout<<finally<<endl;
      }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43874261/article/details/88431592