hdu 1385 spfa和floyd,dijkstra记录最短最小字典序的路径

/*
spfa记录字典序最小的路径
*/
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define inf 0x3fffffff
#define N 1100
int a[N][N];
int b[N];
int n;
int pre[N],dis[N],vis[N];
void init()
{
    memset(pre,-1,sizeof(pre));
    memset(vis,0,sizeof(vis));
}
int Min(int v,int vv)
{
    return v>vv?vv:v;
}
int len;
void dfs(int k,char s[])
{
    if(k==-1)return ;
    dfs(pre[k],s);
    s[len++]=k+'0';
    return ;
}
int cmp(int jnext,int now)
{
    char sf[N],sn[N];
    len=0;
    dfs(jnext,sf);
    sf[len]=0;
    len=0;
    dfs(now,sn);
    sn[len++]=jnext+'0';
    sn[len]=0;
    if(strcmp(sf,sn)>0)
        return  1;
    return 0;
}
void spfa(int s,int t)
{
    int i;
    for(i=1; i<=n; i++)
        dis[i]=inf;
    dis[s]=0;
    queue<int>q;
    q.push(s);
    while(!q.empty())
    {
        int cur=q.front();
        q.pop();
        vis[cur]=0;
        for(i=1; i<=n; i++)
        {
            if(dis[cur]==inf)continue;
            if(a[cur][i]<0||i==cur)continue;
            if(dis[i]>dis[cur]+a[cur][i]+b[i])
            {
                dis[i]=dis[cur]+a[cur][i]+b[i];
                pre[i]=cur;
                if(!vis[i])
                {
                    vis[i]=1;
                    q.push(i);
                }
            }
            else if(dis[i]==dis[cur]+a[cur][i]+b[i]&&cmp(i,cur))//同时要比较如果选cur那么字典序会不会变小
                pre[i]=cur;
        }
    }
    return ;
}
void print(int t)
{
    if(pre[t]==-1)
    {
        printf("%d",t);
        return ;
    }
    print(pre[t]);
    printf("-->%d",t);
    return ;
}
int main()
{
    int i,s,j,t;
    while(scanf("%d",&n),n)
    {
        for(i=1; i<=n; i++)
            for(j=1; j<=n; j++)
                scanf("%d",&a[i][j]);
        for(i=1; i<=n; i++)
            scanf("%d",&b[i]);
        while(scanf("%d%d",&s,&t),s!=-1&&t!=-1)
        {
            int sb=b[s],st=b[t];//这里我认为不需要每次置0
            b[s]=0;//,在下面输出dis[t]-b[t]就可以了,但是wa
            b[t]=0;//
            init();
            spfa(s,t);
            printf("From %d to %d :\n",s,t);
            printf("Path: ");
            print(t);
            printf("\n");
            printf("Total cost : %d\n\n",dis[t]);
            b[s]=sb;//
            b[t]=st;//
        }
    }
    return 0;
}
/*
floyd记录最短字典序最小的路径
*/
#include<stdio.h>
#include<string.h>
#define N 550
#define inf 0x3fffffff
int dis[N][N],path[N][N];
int b[N];
int n;
void floyd()
{
    int i,j,k;
    for(k=1; k<=n; k++)
        for(i=1; i<=n; i++)
            for(j=1; j<=n; j++)
            {
                if(dis[i][k]==inf||dis[k][j]==inf)continue;
                int tmp=dis[i][k]+dis[k][j]+b[k];
                if(dis[i][j]>tmp)
                {
                    dis[i][j]=tmp;
                    path[i][j]=path[i][k];
                }
                else if(dis[i][j]==tmp&&path[i][j]>path[i][k]) //同时判断字典序是否最小
                    path[i][j]=path[i][k];
            }
    return ;
}
int main()
{
    int i,j,k;
    while(scanf("%d",&n),n)
    {
        for(i=1; i<=n; i++)
            for(j=1; j<=n; j++)
            {
                scanf("%d",&dis[i][j]);
                if(dis[i][j]==-1)dis[i][j]=inf;
                path[i][j]=j;
            }
        for(i=1; i<=n; i++)
            scanf("%d",&b[i]);
        floyd();
        int s,t;
        while(scanf("%d%d",&s,&t),s!=-1&&t!=-1)
        {
            printf("From %d to %d :\n",s,t);
            printf("Path: ");
            printf("%d",s);
            k=s;
            while(k!=t)
            {
                k=path[k][t];
                printf("-->%d",k);
            }
            printf("\n");
            printf("Total cost : %d\n\n",dis[s][t]);
        }
    }
    return 0;
}
/*
dijkstar算法求最短最小字典序路径
*/
#include<stdio.h>
#include<string.h>
#define N 550
#define inf 0x3fffffff
int pre[N],dis[N],vis[N];
int a[N][N];
int b[N];
int n;
void init()
{
    memset(vis,0,sizeof(vis));
    memset(pre,-1,sizeof(pre));
}
int len;
void dfs(int k,char s[])
{
    if(k==-1) return ;
    dfs(pre[k],s);
    s[len++]=k+'0';
}
int cmp(int fir,int now)
{
    char sf[N],sn[N];
    len=0;
    dfs(fir,sf);
    sf[len]=0;
    len=0;
    dfs(now,sn);
    sn[len++]=fir+'0';
    sn[len]=0;
    if(strcmp(sf,sn)>0)
        return 1;
    return 0;
}
void dijkstra(int s)
{
    int i,j;
    for(i=1; i<=n; i++)
    {
        if(i==s)continue;//
        dis[i]=a[s][i]+b[i];//初始化注意
        if(a[s][i]<inf)
            pre[i]=s;
    }
    dis[s]=0;
    vis[s]=1;
    for(i=1; i<=n; i++)
    {
        int index,minn=inf;
        for(j=1; j<=n; j++)
            if(minn>dis[j]&&vis[j]==0)
            {
                minn=dis[j];
                index=j;
            }
        vis[index]=1;
        for(j=1; j<=n; j++)
            if(vis[j]==0&&a[index][j]<inf)
            {
                if(dis[j]>dis[index]+a[index][j]+b[j])
                {
                    dis[j]=dis[index]+a[index][j]+b[j];
                    pre[j]=index;
                }
                else if(dis[j]==dis[index]+a[index][j]+b[j]&&cmp(j,index))//和spfa一样判断最小字典序
                    pre[j]=index;
            }
    }
    return ;
}
void print(int k)
{
    if(pre[k]==-1)
    {
        printf("%d",k);
        return ;
    }
    print(pre[k]);
    printf("-->%d",k);
}
int main()
{
    int i,j;
    while(scanf("%d",&n),n)
    {
        for(i=1; i<=n; i++)
            for(j=1; j<=n; j++)
            {
                scanf("%d",&a[i][j]);
                if(a[i][j]==-1)
                    a[i][j]=inf;
            }
        for(i=1; i<=n; i++)
            scanf("%d",&b[i]);
        int s,t;
        while(scanf("%d%d",&s,&t),s!=-1&&t!=-1)
        {
            int sf=b[s],st=b[t];
            b[s]=0;
            b[t]=0;
            init();
            dijkstra(s);
            printf("From %d to %d :\n",s,t);
            printf("Path: ");
            print(t);
            printf("\n");
            printf("Total cost : %d\n\n",dis[t]);
            b[s]=sf;//
            b[t]=st;//
        }
    }
    return 0;
}

    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/u011483306/article/details/45533237
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞