PAT/1003 Emergency +最短路条数以及最短路经过的点的最大和

PAT甲级进度3/155
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​​ 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


n个城市,m条路;每个城市有i个救援队,每条路有j米。
问从起点到终点,最短的路线有几条,并且最多能集齐几只救援队
直接套模板
求最短路径条数以及最短路经过的点的最大和

#include 
#include 
#include 
#include 
#include 
 
 //val储存每个点的值,valsum储存到点【i】前的点值和,
 //path储存点【i】前那个点的号,pathsum储存到点【i】的最短路的条数
using namespace std;
 
 
const int maxn=1e3;
const int INF=1e8;
int n,m,st,en,x,y,z;
int val[maxn],valsum[maxn],path[maxn],pathsum[maxn];
int d[maxn],vis[maxn],G[maxn][maxn];
 
  
void init()
{
    memset(path,0,sizeof(path));
    memset(vis,0,sizeof(vis));
    memset(pathsum,0,sizeof(pathsum));
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<n; j++)
        {
            if(i==j) G[i][j]=0;
            else G[i][j]=INF;
        }
        valsum[i]=val[i];
    }
}
 
 
void dijkstra()
{
    for(int i=0;i<n;i++)
        d[i]=G[st][i];
    d[st]=0;
    pathsum[st]=1;//初始化起点的最短路的条数是1
    int min1,p;
    for(int i=1; i<=n; i++)
    {
        min1=INF;
        for(int j=0; j<n; j++)
        {
            if(!vis[j] && d[j]<min1)
            {
                min1=d[j];
                p=j;
            }
        }
        vis[p]=1;
        for(int j=0; j<n; j++)
        {
            if(!vis[j] && d[j]>d[p]+G[p][j])
            {
                d[j]=d[p]+G[p][j];
                pathsum[j]=pathsum[p];//当松弛时,到【j】和到【p】的最短路的条数相同
                valsum[j]=valsum[p]+val[j];//松弛时直接加上更新后的点值
                path[j]=p;//记录上一个点
            }
            else if(!vis[j] && d[j]==d[p]+G[p][j])
            {
                pathsum[j]+=pathsum[p];//当相等时,到【j】的加上到【p】的
                if(valsum[j]<valsum[p]+val[j])
                {
                    valsum[j]=valsum[p]+val[j];//当相等时加上大的那个
                    path[j]=p;//相等时记录大的那个点
                }
            }
        }
    }
}
 
 
void P()//输出路径
{
    int tmp;
    stack<int>si;
    while(!si.empty()) si.pop();
    si.push(en);//从最后的那个点开始逆序存到堆栈里
    while (st!=en)
    {
        tmp=path[en];
        si.push(tmp);
        en=tmp;
    }
    cout << si.top();
    si.pop();
    while(!si.empty())
    {
        cout << ' ' << si.top();
        si.pop();
    }
    cout << endl;
}
 
 
int main()
{
    scanf("%d%d%d%d",&n,&m,&st,&en);
    for(int i=0; i<n; i++) scanf("%d",&val[i]);
    init();
    for(int i=1; i<=m; i++)
        {scanf("%d%d%d",&x,&y,&z);G[x][y]=z;G[y][x]=z;}//无向图
    dijkstra();
    printf("%d %d\n",pathsum[en],valsum[en]);
    //P();
    return 0;
}

你可能感兴趣的:(PAT甲级)