zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    100到简单加减乘除算法的程序
    安卓日程管理系统中的bug
    绑定到Collection与绑定到CollectionViewSource的不同及解决方案
    【WPF】完美的布局不留白——解决WrapPanel右侧留白问题
    WPF里最简单的控件的Style你能写对么?(默认Style是有问题的)
    WPF Bug清单之(13)——应该出现却没有出现的ListView水平滚动条
    [WPF Bug清单]之(12)——与自定义Attached Property相关的Binding Path运行时错误
    请争取你可以拥有的——即使你不在乎
    C#编码风格——using语句的位置
    【WPF】实现QQ中的分组面板(2)——添加动画
  • 原文地址:https://www.cnblogs.com/ldu-xingjiahui/p/12407460.html
Copyright © 2011-2022 走看看