• String Problem(模板)【最短路】


    String Problem

    题目链接(点击)

    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

    思路:

    ·  开始看题目没看太仔细,没感觉是最短路,因为我只是考虑了上下两个字母之间转换:

             a

             b

          a→b 或者是 b→a

          没考虑到  a→c→d→e

                           b→e 这种情况

    ·  看懂以后就知道是模板题了,有一点不同的是:

              要将字符转换为数字表示最短路,在判断a变为什么的时候要先将a到其余25个点的最短路存进二维数组 (其余字母同理),      下面是代码:

            for(int i=1;i<=26;i++){
                diji(i);
                for(int j=1;j<=26;j++){
                    if(i==j){
                        num[i][j]=0;
                    }
                    else{
                        num[i][j]=dis[j];
                    }
                }
            }

    ·  想知道a最终变成什么就要判断到其余各点距离的最小值

            如果minn==MAX 即表示该点无法通过条件转化成其他字母,要输出 -1

            否则 sum+=minn 

    ·  但要注意:

            两次输入相同的字母关系要取最小的 进行 addnode(将两个点用链式前向星连起来)

    AC代码:

    #include<stdio.h>
    #include<string.h>
    const int MAX=1e5;
    struct node{
        int to;
        int len;
        int next;
    }edge[MAX+5];
    int ans;
    int head[MAX+5];
    void addnode(int u,int v,int w)
    {
        edge[ans].to=v;
        edge[ans].len=w;
        edge[ans].next=head[u];
        head[u]=ans++;
    }
    void allbegin()
    {
        memset(head,-1,sizeof(head));
        ans=0;
    }
    int vis[MAX+5],dis[MAX+5];
    void diji(int s)
    {
        for(int i=1;i<=26;i++){
            dis[i]=MAX;
            vis[i]=0;
        }
        dis[s]=0;
        while(1){
            int k=-1,len=MAX;
            for(int i=1;i<=26;i++){
                if(!vis[i]&&len>dis[i]){
                    k=i;
                    len=dis[i];
                }
            }
            if(k==-1){
                break;
            }
            vis[k]=1;
            for(int j=head[k];~j;j=edge[j].next){
                int t=edge[j].to;
                if(!vis[t]&&dis[t]>edge[j].len+dis[k]){
                    dis[t]=edge[j].len+dis[k];
                }
            }
        }
    }            //上面是迪杰斯特拉模板
    int main()
    {
        int num[55][55],n;
        char a[MAX+5],b[MAX+5],c[MAX+5];
        memset(num,-1,sizeof(num));
        scanf("%s%s",a,b);
        int la=strlen(a);
        int lb=strlen(b);
        scanf("%d",&n);
        allbegin();
        for(int i=1;i<=n;i++){
            int w;
            char u[5],v[5];
            scanf("%s%s%d",u,v,&w);
            int u1=u[0]-'a'+1;
            int v1=v[0]-'a'+1;
            if(num[u1][v1]==-1||num[u1][v1]>w){
                addnode(u1,v1,w);
            }
        }
        if(la!=lb){    //长度不等 直接输出-1
            printf("-1
    ");
        }
        else{     //将26个字母任意两点距离打表
            for(int i=1;i<=26;i++){
                diji(i);
                for(int j=1;j<=26;j++){
                    if(i==j){
                        num[i][j]=0;
                    }
                    else{
                        num[i][j]=dis[j];
                    }
                }
            }
            int sum=0;
            for(int i=0;i<la;i++){
                int a1=a[i]-'a'+1;
                int b1=b[i]-'a'+1;
                if(a1==b1){
                    c[i]=a[i];
                }
                else{  //暴力找出与两个字符 转换值之和最小的 字母(数字代表字母)
                    int minn=MAX;
                    for(int j=1;j<=26;j++){
                        if(num[a1][j]+num[b1][j]<minn){
                            c[i]='a'+j-1;
                            minn=num[a1][j]+num[b1][j];
                        }
                    }
                    if(minn==MAX){  //没有条件将其转换成其他值 结果任然是MAX 输出-1
                        printf("-1
    ");
                        return 0;
                    }
                    else{
                        sum+=minn;
                    }
                }
            }
            printf("%d
    ",sum);
            puts(c);
        }
        return 0;
    }
    
  • 相关阅读:
    JAVAEE学习day01
    learn MongoDB (二) 常用修改器
    learn MongoDB (一) 常用命令行操作
    js事件冒泡和捕获
    vim 常用设置
    void 0 等于 undefined 为什么不直接用undefined
    原生js操作class
    WAI-ARIA roles
    css 效果收集
    前端文章收集
  • 原文地址:https://www.cnblogs.com/ldu-xingjiahui/p/12407460.html
Copyright © 2020-2023  润新知