A1111 Online Map (30 分| Dijkstra算法| dfs深度搜索,附详细注释,逻辑分析)

写在前面

  • 思路分析
    • 给1张地图,两个结点中既有距离也有时间,有单行有双向,要求根据地图推荐两条路线:
      • 1条最快到达路线,1条最短距离路线。
      • 第1行给出2个整数N和M,表示地图中地点个数和路径条数。
      • 接下来M行每1行给出:
        • 道路结点编号V1 道路结点编号V2 是否单行线 道路长度 所需时间 要求第1行输出最快到达时间Time和路径,第2行输出最短距离Distance和路径
    • 分析:
      • 2个Dijkstra
        • 1个求最短路径(如果相同求时间最短那条)
        • 1个求最快路径(如果相同求结点数最小那条)
        • 最短路径,最快路径都可以在Dijkstra⾥面求前驱结点dispre和Timepre数组
          • dispre数组更新的条件是路径更短,或路径相等且时间更短
        • 最快路径多维护1个NodeNum数组,记录在时间最短情况下,到达此节点所需节点数量
          • Time数组更新条件是,时间更短,时间相同此节点能让到达次节点数目变小,则更新Timepre和NodeNum数组
        • 根据dispre 和Timepre数组递归出两路径,比较判断,输出最终答案
  • 知识量、代码量较大
    • 难度较大,学习ing
    • 个人尝试、总结偏少

测试用例

  • input:
    10 15
    0 1 0 1 1
    8 0 0 1 1
    4 8 1 1 1
    3 4 0 3 2
    3 9 1 4 1
    0 6 0 1 1
    7 5 1 2 1
    8 5 1 2 1
    2 3 0 2 2
    2 1 1 1 1
    1 3 0 3 1
    1 4 0 1 1
    9 7 1 3 1
    5 1 0 5 2
    6 5 1 1 2
    3 5
    output:
    Distance = 6: 3 -> 4 -> 8 -> 5
    Time = 3: 3 -> 1 -> 5
    
    intput:
    7 9
    0 4 1 1 1
    1 6 1 1 3
    2 6 1 1 1
    2 5 1 2 2
    3 0 0 1 1
    3 1 1 1 3
    3 2 1 1 2
    4 5 0 2 2
    6 5 1 1 2
    3 5
    output:
    Distance = 3; Time = 4: 3 -> 2 -> 5
    

ac代码

  • #include <iostream>
    #include <algorithm>
    #include <vector>
    using namespace std;
    const int inf = 999999999;
    int dis[510], Time[510], e[510][510], w[510][510], dispre[510],Timepre[510],
        weight[510],NodeNum[510];
    bool visit[510];
    vector<int> dispath, Timepath, temppath;
    int st, fin, minnode = inf;
    
    void dfsdispath(int v)
    {
        dispath.push_back(v);
        if(v == st) return ;
        dfsdispath(dispre[v]);
    }
    void dfsTimepath(int v)
    {
        Timepath.push_back(v);
        if(v == st) return ;
        dfsTimepath(Timepre[v]);
    }
    int main()
    {
        fill(dis, dis + 510, inf);
        fill(Time, Time + 510, inf);
        fill(weight, weight + 510, inf);
        // 距离权
        fill(e[0], e[0] + 510 * 510, inf);
        // 时间权
        fill(w[0], w[0] + 510 * 510, inf);
    
        int n, m;
        scanf("%d %d", &n, &m);
        int a, b, flag, len, t;
        for(int i = 0; i < m; i++)
        {
            scanf("%d %d %d %d %d", &a, &b, &flag, &len, &t);
            e[a][b] = len;
            w[a][b] = t;
            if(flag != 1)
            {
                e[b][a] = len;
                w[b][a] = t;
            }
        }
        // 出发站、到达站
        scanf("%d %d", &st, &fin);
        dis[st] = 0;
        for(int i = 0; i < n; i++)
            dispre[i] = i;
        for(int i = 0; i < n; i++)
        {
            // 查找
            int u = -1, minn = inf;
            for(int j = 0; j < n; j++)
            {
                if(visit[j] == false && dis[j] < minn)
                {
                    u = j;
                    minn = dis[j];
                }
            }
            if(u == -1) break;
            visit[u] = true;
            for(int v = 0; v < n; v++)
            {
                if(visit[v] == false && e[u][v] != inf)
                {
                    // dispre数组更新的条件是路径更短
                    if(e[u][v] + dis[u] < dis[v])
                    {
                        dis[v] = e[u][v] + dis[u];
                        dispre[v] = u;
                        weight[v] = weight[u] + w[u][v];
                    }
                    // 路径相等且时间更短
                    else if(e[u][v] + dis[u] == dis[v] && weight[v] > weight[u]+ w[u][v])
                    {
                        weight[v] = weight[u] + w[u][v];
                        dispre[v] = u;
                    }
                }
            }
        }
        dfsdispath(fin);
    
        Time[st] = 0;
        fill(visit, visit + 510, false);
        for(int i = 0; i < n; i++)
        {
            int u = -1, minn = inf;
            for(int j = 0; j < n; j++)
            {
                if(visit[j] == false && minn > Time[j])
                {
                    u = j;
                    minn = Time[j];
                }
            }
            if(u == -1) break;
            visit[u] = true;
            for(int v = 0; v < n; v++)
            {
                if(visit[v] == false && w[u][v] != inf)
                {
                    // Time数组更新条件是,时间更短
                    if(w[u][v] + Time[u] < Time[v])
                    {
                        Time[v] = w[u][v] + Time[u];
                        Timepre[v]=(u);
                        NodeNum[v]=NodeNum[u]+1;
                    }
                    // 时间相同此节点能让到达次节点数目变小
                    else if(w[u][v] + Time[u] ==
                            Time[v]&&NodeNum[u]+1<NodeNum[v])
                    {
                        Timepre[v]=(u);
                        NodeNum[v]=NodeNum[u]+1;
                    }
                }
            }
        }
        dfsTimepath(fin);
        printf("Distance = %d", dis[fin]);
        if(dispath == Timepath)
            printf("; Time = %d: ", Time[fin]);
        else
        {
            printf(": ");
            for(int i = dispath.size() - 1; i >= 0; i--)
            {
                printf("%d", dispath[i]);
                if(i != 0) printf(" -> ");
            }
            printf("\nTime = %d: ", Time[fin]);
        }
        for(int i = Timepath.size() - 1; i >= 0; i--)
        {
            printf("%d", Timepath[i]);
            if(i != 0) printf(" -> ");
        }
        return 0;
    }
    
发布了328 篇原创文章 · 获赞 107 · 访问量 39万+

猜你喜欢

转载自blog.csdn.net/qq_24452475/article/details/100618033