codevs 1062 路由选择 最短路次短路 dijkstra 解题报告

题目描述 Description

在网络通信中,经常需要求最短路径。但完全用最短路径传输有这样一个问题:如果最终在两个终端节点之间给出的最短路径只有一条。则在该路径中的任一个节点或链路出现故障时,信号传输将面临中断的危险。因此,对网络路由选择作了以下改进:

为任意两节点之间通信提供三条路径供其选择,即最短路径、第二最短路径和第三最短路径。

第一最短路径定义为:给定一个不含负回路的网络D={V,A,W},其中V={v1,v2,…,vn},A为边的集合,W为权的集合,设P1是D中最短(v1,vn)路。称P1为D中最短(v1,vn)路径,如果D中有一条(v1,vn)路,P2满足以下条件:

(1)P2≠P1;(2)D中不存在异于P1的路P,使得:

(3)W(P1)≤W(P)

输入描述 Input Description

输入: n S T Max (每格数值之间用空格分隔)

    M11  M12  …  M1n

    M21  M22  …  M2n

          …   … 

    Mn1  Mn2  …  Mnn

其中,n为节点数,S为起点,T为终点,Max为一代表无穷大的整数,Mij描述I到J的距离,若Mij=Max,则表示从I到J无直接通路,Mii=0。

输出描述 Output Description

输出:三条路径(从小到大输出),每条路径占一行,形式为:路径长度 始点…终点 (中间用一个空格分隔)

样例输入 Sample Input

5 1 5 10000

0 1 3 10000 7

10000 0 1 10000 10000

10000 10000 0 1 4

10000 10000 10000 0 1

10000 1 10000 10000 0

样例输出 Sample Output

4 1 2 3 4 5

5 1 3 4 5

6 1 2 3 5

思路

次短路

代码

#include<cstdio>
using namespace std;
const int N=50+3;
const int inf=1000000009;
int n;
int d[N][N],dist[3][N],vis[3][N],step[3][N][N];
void dijkstra(int S)
{
    int i,j,tm,u,v,k,l;
    for (i=1;i<=n;i++)
    for (j=0;j<3;j++)
    dist[j][i]=inf;
    for (i=1;i<=n;i++)
    if (i!=S&&d[S][i]<inf) dist[0][i]=d[S][i],step[0][i][++step[0][i][0]]=S;
    dist[0][S]=0;
    step[0][S][0]=0;
    vis[0][S]=1;
    for (i=1;i<n*3;i++)
    {
        for (j=1,tm=inf,u=v=1;j<=n;j++)
        for (k=0;k<3;k++)
        if (!vis[k][j]&&tm>dist[k][j]) {tm=dist[k][j];u=k;v=j;}
        vis[u][v]=1;
        for (j=1;j<=n;j++)
        if (v!=j)
        {
            k=dist[u][v]+d[v][j];
            if (!vis[0][j]&&k<=dist[0][j])
            {
                dist[2][j]=dist[1][j];
                step[2][j][0]=step[1][j][0];
                for (l=1;l<=step[1][j][0];l++) step[2][j][l]=step[1][j][l];
                dist[1][j]=dist[0][j];
                step[1][j][0]=step[0][j][0];
                for (l=1;l<=step[0][j][0];l++) step[1][j][l]=step[0][j][l];
                dist[0][j]=k;
                for (l=0;l<=step[u][v][0];l++) step[0][j][l]=step[u][v][l];
                step[0][j][++step[0][j][0]]=v;
            }
            else if (!vis[1][j]&&k<dist[1][j])
            {
                dist[2][j]=dist[1][j];
                step[2][j][0]=step[1][j][0];
                for (l=1;l<=step[1][j][0];l++) step[2][j][l]=step[1][j][l];
                dist[1][j]=k;
                for (l=0;l<=step[u][v][0];l++) step[1][j][l]=step[u][v][l];
                step[1][j][++step[1][j][0]]=v;
            }
            else if (!vis[2][j]&&k<dist[2][j])
            {
                dist[2][j]=k;
                for (l=0;l<=step[u][v][0];l++) step[2][j][l]=step[u][v][l];
                step[2][j][++step[2][j][0]]=v;
            }
        }
    }
}
int main()
{
    int S,T,ig,i,j;
    scanf("%d%d%d%d",&n,&S,&T,&ig);
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=n;j++)
        {
            scanf("%d",&d[i][j]);
            if(d[i][j]==ig) d[i][j]=inf;
        }
    }
    dijkstra(S);
    printf("%d ",dist[0][T]);
    for (i=1;i<=step[0][T][0];i++) 
    printf("%d ",step[0][T][i]);printf("%d\n",T);
    printf("%d ",dist[1][T]);
    for (i=1;i<=step[1][T][0];i++) 
    printf("%d ",step[1][T][i]);printf("%d\n",T);
    printf("%d ",dist[2][T]);
    for (i=1;i<=step[2][T][0];i++) 
    printf("%d ",step[2][T][i]);printf("%d\n",T);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值