PAT 甲級1003 Emergency (25)(25 分)(Dikjstra,也可以自己到自己!)


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

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, C1 and C2 - 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, c2 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 C1 to C2.

Output

For each test case, print in one line two numbers: the number of different shortest paths between C1 and C2, 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

1003.突發事件(25)

作為一個城市緊急援救隊的指揮者,你得到了一個國家的特殊地圖。地圖上分散着幾座城市,城市間用道路連接着。每個城市援救隊的數量以及兩座城市之間每條道路的長度已經在地圖上標出。當某些城市發生了突發事件,需要你的幫助時,你的工作是帶領你的隊伍盡快的趕到事發現場,與此同時,召集盡可能多的在路上的隊伍。

 

輸入

每個輸入文件包含一個測試實例。每個實例的第一行有四個正整數:N(<= 500)是城市的個數(城市的編號從0到N-1),M是道路的個數,C1和C2分別是你現在所在的城市以及你必須去救援的城市。下一行有N個整數,第i個整數是第i個城市中救援隊的數量。然后下面有M行,每行表示一條道路。每一行有三個整數c1,c2和L,分別表示道路連接的兩個城市以及道路的長度。保證C1到C2之間存在至少一條路徑。

 

輸出

對於每個測試實例,在一行中輸出兩個數字:C1和C2之間不同的最短路徑的個數,你能聚集起來的最多的救援隊數量。

一行中的所有數字必須被一個空格分隔開,在每行的結尾不允許出現空格。

題解:

本題我用了Dijstra,你可以什么都別管先打個Dijstra模版。

然后考慮最短路條數:

  一開始,和C1相連的所有點的最短路數初始化為1,包括C1(可能自己到自己),其它初始化為0,。

  當d[k]+e[k][j]<d[j](通過k可以對C1到 j 可以更新)時,ti[j]=ti[k],(ti[p]表示C1到p的最短路條數),因為既然更新,肯定直接可以把原來的ti【j】覆蓋了

  當 d[k]+e[k][j]==d[j],ti[j]+=ti[k];條數就可以增加了,但不是+1,是加上ti[k]。

然后考慮人數最多:

  一開始,我只初試化了C1:rm[c1]=r[c1];C1的人數最多的就是為r[c1]。

  之后Dijstra每挑選出一個k都檢查一下:rm[k]=max(rm[k],r[k]+r[s]);

  當d[k]+e[k][j]<d[j],rm[j]=rm[k]+r[j];

  當d[k]+e[k][j]==d[j],rm[j]=max(rm[j],rm[k]+r[j]);

與第二組測試數據類似,我被卡的樣例:

 

3 2 1 1
0 1 2
0 1 1
1 2 1

 

應該為1 1

 

#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;
int e[505][505];
int ti[505];
int r[505];
int rm[505];
int v[505];
int d[505];
int n,m;
int c1,c2;
int ss=0;
void dijstra(int s)
{
    for(int i=1;i<=n;i++) d[i]=e[s][i];
    d[s]=0;
    v[s]=1;
    while(1)
    {
        int mm=inf;
        int k=-1;
        for(int i=1;i<=n;i++)
        {
            if(!v[i]&&mm>d[i])
            {
                k=i;
                mm=d[i];
            }
        }
        if(k==-1) break;
        v[k]=1;
        rm[k]=max(rm[k],r[k]+r[s]);
        for(int j=1;j<=n;j++)
        {
            if(d[k]+e[k][j]<d[j])
            {
                d[j]=d[k]+e[k][j];
                ti[j]=ti[k];
                rm[j]=rm[k]+r[j];
            }
            else if(d[k]+e[k][j]==d[j])
            {
                ti[j]+=ti[k];
                rm[j]=max(rm[j],rm[k]+r[j]);
            }
        }
    }
}
int main()
{
    while(cin>>n>>m>>c1>>c2)
    {
        c1++;
        c2++;
        memset(e,inf,sizeof(e));
        memset(ti,0,sizeof(ti));
        memset(v,0,sizeof(v));
        memset(rm,0,sizeof(rm));
        ss=0;
        for(int i=1;i<=n;i++)
        {
            cin>>r[i];
        }
        for(int i=1;i<=m;i++)
        {
            int x,y,z;
            cin>>x>>y>>z;
            x++;
            y++;
            if(e[x][y]&&x==c1||y==c1)
            {
                if(x==c1)
                    ti[y]++;
                else ti[x]++;
            }

            if(e[x][y]>z)
                e[x][y]=e[y][x]=z;
        }
        rm[c1]=r[c1];
        ti[c1]=1;
        dijstra(c1);
        cout<<ti[c2]<<" "<<rm[c2]<<endl;
    }
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM