pat-甲-1003

题目

1003 Emergency (25 分)
As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the length of each road between any pair of cities are marked on the map. When there is an emergency call to you from some other city, your job is to lead your men to the place as quickly as possible, and at the mean time, call up as many hands on the way as possible.
Input Specification:
Each input file contains one test case. For each test case, the first line contains 4 positive integers: N (≤500) - the number of cities (and the cities are numbered from 0 to N−1), M - the number of roads, C 1 C_​1 and C 2 C_​2 ​​ - the cities that you are currently in and that you must save, respectively. The next line contains N integers, where the i-th integer is the number of rescue teams in the i-th city. Then M lines follow, each describes a road with three integers c1 , c​2​​ and L, which are the pair of cities connected by a road and the length of that road, respectively. It is guaranteed that there exists at least one path from C​1 to C​2
​​ Output Specification:
For each test case, print in one line two numbers: the number of different shortest paths between C​1​​ and C​2, and the maximum amount of rescue teams you can possibly gather. All the numbers in a line must be separated by exactly one space, and there is no extra space allowed at the end of a line.

思路

  • 题目要求是在图上找两点之间的最短路径数最多的rescue teams数量,则要求最短路,且要统计最短路的数量,还要记录最大team的数量。
  • 求最短路,使用Dijkstra算法,并在求最短路时统计最短路数量和team数
  • Dijkstra算法
    • 是单源最短路算法
    • 需要记录每个节点的前驱,到起点的距离,是否加入路径
      • 对于本题,还要记录起点到该节点之间的最短路径之和,节点上的team数,以及从起点到该节点最短路径上最多team的数量。
    • 对于边,只需要记录两个节点和边上权重
  • 如何计算最短路径数
    • 为什么会出现多条最短路径
      • 从起点到某个点有多条最短路径,而该点是终点或是起点到终点最短路径上的一点
    • 最短路径数是前驱节点最短路径数之和。如有多个前驱,则最短路基数是每个前驱节点最短路径数之和
  • team数量 ,类似于最短路径数的计算,自身的team数量加上前驱节点中最大的team数量。
#include <iostream>

using namespace std;
struct Node{
 int pre;
 int dis;
 int in;
 int roads;
 int team ;
 int totalTeam;
};
struct Road{
  int c1;
  int c2;
  int dis;
};
int INT_MAX = 100000;
int link(int ,Road);

int main()
{
    int i ,number ,rnumber ,now ,next,dis = 0 ,aim ,j,another,k;
    // 初始化
    if(4!=scanf("%d %d %d %d",&number,&rnumber,&now,&aim))
       return -2;
    Node nodes[number];
    Road roads[rnumber];
    for(i=0;i<number;i++){
     if(1 != scanf("%d",&(nodes[i].team)))
        return -2;
      nodes[i].totalTeam = nodes[i].team;
      nodes[i].pre=-1;
      nodes[i].dis = INT_MAX;//将所有点到起点的距离设为无穷大
      nodes[i].in=0; //not in
      nodes[i].roads = 0 ;
    }
    // 将起点加入最短路径
    nodes[now].in = 1;
    nodes[now].pre = aim;
    nodes[now].dis = 0;
    nodes[now].roads = 1;

   for(i=0;i<rnumber;i++){
     if(3!=scanf("%d %d %d",&(roads[i].c1),&(roads[i].c2),&(roads[i].dis)))
        return -2;
   }
// 计算最短路 
    for(k=1;k<number;k++){ // 已经加入一个节点,故只需要循环number-1次
         //更新起点到各节点之间的距离
          for(j=0;j<rnumber;j++){
            another = link(now,roads[j]);
           
           if( another != -1 && !nodes[another].in && 
                                 nodes[now].dis+roads[j].dis <nodes[another].dis){
               // 该节点的最短路径被更新
             nodes[another].dis= nodes[now].dis+roads[j].dis;
             nodes[another].pre = now;
             // 重置该节点的最短路径数
             nodes[another].roads = nodes[now].roads; 
             //重置该节点的team数
             nodes[another].totalTeam = nodes[now].totalTeam +nodes[another].team;  
           }else if(another != -1 && !nodes[another].in &&
                                   nodes[now].dis+roads[j].dis == nodes[another].dis){
                //该节点有多个前驱节点 ,累加最短路径数
               nodes[another].roads += nodes[now].roads;         
               // 求最大team数  
               nodes[another].totalTeam = (nodes[another].totalTeam>nodes[now].totalTeam+nodes[another].team)?
                       nodes[another].totalTeam:nodes[now].totalTeam+nodes[another].team;
           }
        }
        next =-1;
        dis = INT_MAX;
        for(i=0;i<number;i++){  // loop nodes_number-1 times;
            if(nodes[i].in){
                for(j=0;j<rnumber;j++){
                        another = link(i,roads[j]);
                    if( another != -1 && !nodes[another].in && dis>nodes[i].dis+roads[j].dis){
                            // change informatin
                        dis = nodes[i].dis+roads[j].dis;
                        next = another;
                    }
                }
            }

        }//for cnumber

        if(next == -1){
            return -2;

        }
        // 将节点加入最短路径
        nodes[next].in = 1;
        now = next;
    }//while

   cout<<nodes[aim].roads<<" "<<nodes[aim].totalTeam<<endl;
}

int link(int n,Road r){
    int another ;
    if(r.c1==n){
        another = r.c2;
    }else if(r.c2 == n){
       another = r.c1;
    }else{
       another = -1;
    }
    return another;
}


猜你喜欢

转载自blog.csdn.net/qq_38420683/article/details/86562093