zoukankan      html  css  js  c++  java
  • 1062 路由选择

    1062 路由选择

     

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 钻石 Diamond
     
     
     
    题目描述 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)<W(P2)

    则称P2为D的第二最短路径。

        第三最短路径的定义为:设P2是D中第二最短(v1,vn)路径,如果D中有一条(v1,vn)路P3满足以下条件:

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

    (3)W(P2)≤W(P)<W(P3)

    则称P3为D中第三最短路径。

        现给定一有N个节点的网络,N≤30,求给定两点间的第一、第二和第三最短路径。

    输入描述 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

    数据范围及提示 Data Size & Hint
     

    分类标签 Tags 点此展开 

     
     
    题解:

    暴力就好了,存路径的时候注意处理一下。

    第一次输出路径的递归写炸了,RE,25

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    #define N 35
    int n,S,T,maxn;
    int f[N][N],dis[N][N],pre[N][N];
    short ans[N];
    bool vis[N][N];
    void print(int x){
        if(!pre[S][x]) return ;
        print(pre[S][x]);
        printf("%d ",x);
        ans[++ans[0]]=x;
    }
    void out(int x){
        if(!pre[S][x]) return ;
        out(pre[S][x]);
        printf("%d ",x);
    }
    int main(){
        scanf("%d%d%d%d",&n,&S,&T,&maxn);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                scanf("%d",&dis[i][j]);
                if(dis[i][j]!=maxn&&dis[i][j]) pre[i][j]=i;
            }
        }
        memcpy(f,dis,sizeof dis);
        for(int k=1;k<=n;k++){
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    if(i!=j&&j!=k&&i!=k){
                        if(dis[i][j]>dis[i][k]+dis[k][j]){
                            dis[i][j]=dis[i][k]+dis[k][j];
                            pre[i][j]=pre[k][j];
                        }
                    }
                }
            }
        }
        printf("%d ",dis[S][T]);
        printf("%d ",S);ans[++ans[0]]=S;print(T);putchar('
    ');
        //for(int i=1;i<=ans[0];i++) printf("%d ",ans[i]);
        int res=0x7fffffff,jx,jy,u,v;
        for(int i=1;i<ans[0];i++){
            u=ans[i];
            for(int j=i+1;j<=ans[0];j++){
                v=ans[j];
                if(f[u][v]>dis[u][v]&&f[u][v]-dis[u][v]<res){
                    res=f[u][v]-dis[u][v];
                    jx=u;
                    jy=v;
                }
            }
        }
        vis[jx][jy]=1;
        printf("%d ",dis[S][T]+res);
        int t=pre[S][jy];
        pre[S][jy]=jx;
        //cout<<jx<<","<<jy<<":"<<t<<"->"<<jx<<endl;
        printf("%d ",S);out(T);putchar('
    ');
        pre[S][jy]=t;
        res=0x7fffffff;
        for(int i=1;i<ans[0];i++){
            u=ans[i];
            for(int j=i+1;j<=ans[0];j++){
                v=ans[j];
                if(!vis[u][v]&&f[u][v]>dis[u][v]&&f[u][v]-dis[u][v]<res){
                    res=f[u][v]-dis[u][v];
                    jx=u;
                    jy=v;
                }
            }
        }
        printf("%d ",dis[S][T]+res);
        pre[S][jy]=jx;
        /*cout<<jx<<","<<jy<<":"<<t<<"->"<<jx<<endl;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                printf("%6d",pre[i][j]);
            }
            printf("
    ");
        }*/
        printf("%d ",S);out(T);putchar('
    ');
        return 0;
    }

    更新:

    floyed换成dijkstra;不再用递归输出路径

    思路来自以前的次短路题目:http://www.cnblogs.com/shenben/p/5741741.html(最短路与次短路的关系,次短路与第三短路的关系同理)

    题解:

    dis[0][T]表示S->T的最短路;(1)
    dis[1][T]表示S->T的次短路;(2)
    dis[2][T]表示S->T的第三短路;(3)
    step[][][]模拟vector存路径
    step[0][T][0]表示(1) S->T需要经过几个点。输出step[0][T][0]->step[0][T][step[0][T][0]]即可。
    step[1][T][0],step[2][T][0]同样
    和普通dijkstra大致一样,再加上三维表示更新哪一短路。
    更新时,有三种情况:
    1、有比最短路短的k:(3)=(2);(2)=(1);(1)=k;
    2、有比次短路短的k:(2)=(1);(1)=k;
    3、有比第三短路短的k:(1)=k;
    1 2 3情况更新dis时,同时要更新step

    详见代码。

    AC代码:

    #include<cstdio>
    #define N 50
    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
    ",T);
        printf("%d ",dist[1][T]);
        for(i=1;i<=step[1][T][0];i++) printf("%d ",step[1][T][i]);printf("%d
    ",T);
        printf("%d ",dist[2][T]);
        for(i=1;i<=step[2][T][0];i++) printf("%d ",step[2][T][i]);printf("%d
    ",T);
        return 0;
    }
  • 相关阅读:
    新增html元素的使用
    音频的使用和插入以及动态文字的使用
    创建表单以及表单元素的使用
    今天学习image在html中的应用
    Repeater里查找控件
    CSS 基础教程
    自然图像的颜色统计特征 Image Color Statistics
    [转]UE中使用正则表达式的一些技巧
    [转]SQL Server 的事务和锁
    [转]Amtura 商务智能项目实现手记
  • 原文地址:https://www.cnblogs.com/shenben/p/5753387.html
Copyright © 2011-2022 走看看