地址:http://codeforces.com/contest/33/problem/B
很老的题了,今天被学长拉出来,就做做看。
题意:给出两个字符串,给出n个 a b x,表明字符a可以变成b,每次花费为x。问要想把这俩字符串变成一样的,最少花费多少。无法变就输出-1。
解析:刚开始以为,每次只看同一个位置,能互换就行,洋洋洒洒写了100多行,一直WA7。原来,一个字符,不一定要变成另一个字符串对应位置的那个字符,可以变成其它的,只要保证花费最小就行。所以我们把26个字母之间互换的花费存起来,跑一遍floyd,就得出了两两变化的最小花费,然后每次看一个位置,就遍历26个字符,看同一位置的这俩字符变成同一个字符所需的花费,求最小就可以了。如果最小值得不到更新,就说明这两个字符串没办法变成同样的,输出-1。
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int inf = 0x3f3f3f3f;
int mp[28][28];
char mid[maxn];
char s1[maxn],s2[maxn];
int d[28][28];
void init()
{
for(int i= 0;i<26;i++)
for(int j=0;j<26;j++)
{
if(i==j)
mp[i][j]=0;
else
mp[i][j]=inf;
}
}
void floyd()
{
for(int i=0;i<26;i++)
for(int j=0;j<26;j++)
d[i][j]=mp[i][j];
for(int k=0;k<26;k++)
for(int i=0;i<26;i++)
for(int j=0;j<26;j++)
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
int main()
{
cin>>s1;
cin>>s2;
int len1=strlen(s1),len2=strlen(s2);
int n;
cin>>n;
init();
char ch1;
while(n--)
{
scanf(" %c",&ch1);
char ch2;
int x;
scanf(" %c %d",&ch2,&x);
int a=ch1-'a';
int b=ch2-'a';
mp[a][b]=min(mp[a][b],x);
}
if(len1!=len2)
{
cout<<"-1"<<endl;
return 0;
}
floyd();
int ok=0;
int tot=0;
int sum=0;
for(int i=0;i<len1;i++)
{
if(s1[i]==s2[i])
{
mid[tot++]=s1[i];
continue;
}
int minn=inf;
int a=s1[i]-'a';
int b=s2[i]-'a';
for(int j=0;j<26;j++)
{
int x1=d[a][j];
int x2=d[b][j];
if(x1!=inf&&x2!=inf&&minn>(x1+x2))
{
minn=x1+x2;
mid[tot]=char('a'+j);
}
}
if(minn==inf)
{
ok=1;break;
}
// cout<<minn<<endl;
tot++;
sum+=minn;
}
if(ok)
cout<<"-1"<<endl;
else
{
cout<<sum<<endl;
cout<<mid<<endl;
}
}