PAT_甲级_1003 Emergency (25分) (C++)

目录

1,题目描述

题意解析:

输入:

输出:

2,思路

Dijkstra算法

注意点:

3,代码


1,题目描述

Sample Input:

5 6 0 2
1 2 1 5 3
0 1 1
0 2 2
0 3 1
1 2 1
2 4 1
3 4 1

Sample Output:

2 4

题意解析:

目的城市发生事故,需要从所在城市赶往目的城市,寻找最短路径,并且在路中联系尽可能多的救护队前往救护。

题目保证任意两城市间至少有一条路

输入:

第一行:城市的数目N,路的数目M,所在城市编号C1,目的城市编号C2

第二行:N个城市对应各自救护队的数目

剩下M行:连接的两个城市编号C1、C2,及路的长度

输出:

从C1到C2不同最短路径的数目;

最短路径中可以集合的救护队的最多数目;

2,思路

意思很清楚,就是利用dijkstra算法;想再复习一下算法的同学可以戳这里@ heroacool 【数据结构--Dijkstra算法最清楚的讲解】

这里再简单描述一下:

Dijkstra算法

此算法用于解决图中从一点到其他所有顶点的最短路径问题;

  1. 从一个初始顶点出发,遍历邻近的所有顶点,取出最近的顶点放入visited中;
  2. 遍历visited数组中顶点邻近的所有顶点,找到最近的顶点放入visited中;
  3. 重复以上步骤2,直至所有顶点均遍历一遍;

注意点:

  1. 题目的限制,城市数量小于等于500;
  2. 注意记录最短路径的数目(小于当前最短路径时,更新;等于当前最短路径时,累加)和到达节点累加的点权值(小于当前最短路径时,更新;等于当前最短路径时,取最大值);
  3. 由于每个点的最短路径的数目和累加的点权值都需要记录,故均为他们开辟数组;

3,代码

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
using namespace std;

int main(){
//#ifdef ONLINE_JUDGE
//#else
//    freopen("1.txt", "r", stdin);
//#endif

    int n, m, c1, c2;           //n:城市数 m:路数 c1:所在城市 c2:目的城市
    int graph[500][500];        //邻接矩阵 记录边的权值
    int weight[500];            //每个城市的救护队数目
    int weight_[500];           //到达每个点累计的最多救护队数目
    int dis[500];               //到达每个顶点的最短距离
    int num[500];               //到达每个顶点的最短路径的数目
    bool visited[500];          //是否已访问
    int inf = 99999999;   //无穷大

    scanf("%d%d%d%d", &n, &m, &c1, &c2);    //%d间不用加空格
    for(int i = 0 ; i < n ; i++){
        scanf("%d", &weight[i]);
    }
    fill(graph[0], graph[0]+500*500, inf);  //二维数组 graph[0]!!!
    fill(dis, dis+500, inf);
    for(int i = 0 ; i < m ; i++){
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        graph[a][b] = graph[b][a] = c;      //无向图
    }

    dis[c1] = 0;                            //c1与自己距离为0
    weight_[c1] = weight[c1];               //c1点救护队数目
    num[c1] = 1;                            //到达c1路径数目

    for(int i = 0 ; i < n ; i++){
        int u = -1;
        int minDis = inf;                   //记录最短的边 来确定下一个点

        for(int j = 0 ; j < n ; j++){       //寻找距已遍历节点中最近的相邻节点 第一次u=起始点
            if(visited[j] == false && dis[j] < minDis){
                u = j;
                minDis = dis[j];
            }
        }
        if(u == -1) break;
        visited[u] = true;                  //访问此点

        for(int v = 0; v < n; v++){
            if(visited[v] == false && graph[u][v] != inf){      //该节点未被访问 且 两节点间有通路
                if(dis[u] + graph[u][v] < dis[v]){              //更新最短路径
                    dis[v] = dis[u] + graph[u][v];
                    num[v] = num[u];                            //重置路径数目
                    weight_[v] = weight_[u] + weight[v];
                }else if(dis[u] + graph[u][v] == dis[v]){       //最短路径数目增加
                    num[v] += num[u];                           //最短路径数目=到v最短路径数目+到u最短路径数目
                    if(weight_[v] < weight_[u] + weight[v]){    //更新救护队数目最大值
                        weight_[v] = weight_[u] + weight[v];
                    }
                }

            }
        }

    }

    printf("%d %d", num[c2], weight_[c2]);

    return 0;
}
发布了45 篇原创文章 · 获赞 5 · 访问量 2199

猜你喜欢

转载自blog.csdn.net/qq_41528502/article/details/104179806