[PAT甲級]1003 Emergency

求最短路徑的問題,用dj算法來解決,注意添加了條件,當路徑長度相等時,優先選擇救援隊較多的路徑;其次,要算出最短路徑的條數,可以設置num_t[100]數組,記錄從開始結點到當前結點 i 的最短路徑的條數,而後面的相鄰結點 j 若可以通過 i 以最短路徑長度到達則 += num_s[i]即可,每次獲得一個newP即是知道它的所有最短路徑,找出所有能直連它的已經加入到newP過的即可。

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​​ and 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 c​1​​, 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.

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

輸出的是最短路徑的條數,以及最短路徑的最多救援隊數,代碼爲:

#include<cstdio>
#include<vector>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;

struct E{
    int next;
    int c;
    int num;//走這條路可以獲得的援救隊伍數量,只要加上next的數量即可,開始時記錄開始結點的隊伍的數量
};

vector<E> edge[100000];
bool mark[501];//是否已經訪問過
int Dis[501];//由開始結點到相應結點的當前已知最短距離
int num_t[501];//第i座城市的救援隊數量
int Count[501];//從開始結點到當前城市的總救援隊數量
int num_s[501] = {0};//從開始結點到當前結點最短的路線共有幾條

int main()
{
    int N, M, C1, C2;
    scanf("%d%d%d%d", &N, &M, &C1, &C2);
    for(int i = 0; i < N; i++)
    {
        scanf("%d", &num_t[i]);
    }
    for(int i = 0; i < M; i++)
    {
        int s, e, cost;
        scanf("%d%d%d", &s, &e, &cost);
        E temp;
        temp.next = e;
        temp.c = cost;
        temp.num = num_t[e];
        edge[s].push_back(temp);
        temp.next = s;
        temp.num = num_t[s];
        edge[e].push_back(temp);
    }
    for(int i = 0; i < N; i++)
    {
        Dis[i] = -1;
        mark[i] = false;
    }
    mark[C1] = true;
    Dis[C1] = 0;
    Count[C1] = num_t[C1];
    int newP = C1;
    num_s[C1] = 1;
    for(int i = 1; i < N; i++)
    {
        for(int j = 0; j < edge[newP].size(); j++)
        {
            int t = edge[newP][j].next;
            int co = edge[newP][j].c;
            int n = edge[newP][j].num;
            if(mark[t] == true) continue;
            if(Dis[t] == -1 || Dis[t] > Dis[newP] + co || (Dis[t] == Dis[newP] + co && Count[newP] + n > Count[t]))
            {
                Count[t] = Count[newP] + n;
                Dis[t] = Dis[newP] + co;
            }
        }
        int minV = 0x7fffffff;
        for(int k = 0; k < N; k++)
        {
            if(mark[k] == true) continue;
            if(Dis[k] == -1) continue;
            if(minV > Dis[k])
            {
                newP = k;
                minV = Dis[k];
            }
        }
        //新加入一個已知最短路徑,則從開始結點到 newP 的結點都是已經知道的
        for(int j = 0; j < N; j++)
        {
            if(mark[j] == true && j != newP)
            {
                for(int k = 0; k < edge[j].size(); k++)
                {
                    if(newP == edge[j][k].next && Dis[newP] == Dis[j] + edge[j][k].c)
                    {
                        num_s[newP] += num_s[j];
                    }
                }
            }
        }
        mark[newP] = true;
    }
    printf("%d %d\n", num_s[C2], Count[C2]);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章