甲级-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, 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 Specification:

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

解题思路:

使用迪杰斯特拉算法,需要注意统计保存最短路径的数量,最后选择权值最高(途径结点救援队数量总和最多)的路径。

代码:

编译器:C++(g++)

#include 
#include 
using namespace std;
typedef vector RoadInfo;

//查找未被访问过的,距离c1路径长度最小的结点
int findMin(vector &roadLst)
{
    int min=-1,index=-1;
    int n=roadLst.size();
    for(int i=0;i!=n;++i)
    {
        if(roadLst[i][n+2]!=1&&roadLst[i][n+1]!=-1)
        {
            if(-1==min)
            {
                min=roadLst[i][n+1];
                index=i;
            }
            else
            {
                if(roadLst[i][n+1]>n>>m>>c1>>c2;
    vector numOfCity;
    for(int i=0;i!=n;++i)
    {
        int tmp;
        cin>>tmp;
        numOfCity.push_back(tmp);
    }
    vector> road;
    for(int i=0;i!=m;++i)
    {
        int t1,t2,t3;
        cin>>t1>>t2>>t3;
        vector t;
        t.push_back(t1);
        t.push_back(t2);
        t.push_back(t3);
        road.push_back(t);
        //swap一下t[0]和t[1]再push,这样后面只用遍历t[0]就可以了
        std::swap(t[0],t[1]);
        road.push_back(t);
    }
    //c1到此节点的路程信息,0~n-1表示经过的节点,n为同等长度的路径数量,n+1为路径长度,n+2为是否以此节点为中心访问过
    RoadInfo ri(n+3,-1);
    vector roadLst(n,ri);
    for(int i=0;i!=2*m;++i)
    {
        //以c1为出发点遍历
        if(c1==road[i][0])
        {
            roadLst[road[i][1]][c1]=1;
            roadLst[road[i][1]][n]=1;
            roadLst[road[i][1]][n+1]=road[i][2];
        }
    }
    roadLst[c1][n]=1;   //c1到c1的路径只有1条
    roadLst[c1][n+1]=0; //c1到c1的距离为0
    roadLst[c1][n+2]=1; //将c1结点置为已访问状态
    while(1)
    {
        int min=findMin(roadLst);   //查找未被访问过的,距离c1路径长度最小的结点
        if(-1==min||min==c2)    //如果min==c2,则表明此时c1到c2的最短路径已经确认
        {
            break;
        }
        for(int i=0;i!=2*m;++i)
        {
            if(min==road[i][0])
            {
                if(-1==roadLst[road[i][1]][n+1])
                {
                    roadLst[road[i][1]]=roadLst[min];
                    roadLst[road[i][1]][min]=1;
                    roadLst[road[i][1]][n+1]+=road[i][2];
                    roadLst[road[i][1]][n+2]=-1;
                }
                else
                {
                    if(roadLst[road[i][1]][n+1]>roadLst[min][n+1]+road[i][2])
                    {
                        int visited=roadLst[road[i][1]][n+2];
                        roadLst[road[i][1]]=roadLst[min];
                        roadLst[road[i][1]][min]=1;
                        roadLst[road[i][1]][n+1]+=road[i][2];
                        roadLst[road[i][1]][n+2]=visited;
                    }
                    //路径长度相同,则比较哪条路上的救援队数量多,选择多的那一条
                    else if(roadLst[road[i][1]][n+1]==roadLst[min][n+1]+road[i][2])
                    {
                        int sumOfRoad=roadLst[road[i][1]][n]+roadLst[min][n];
                        int curTeams=0,preTeams=0;
                        for(int j=0;j!=n;++j)
                        {
                            if(1==roadLst[road[i][1]][j])
                                preTeams+=numOfCity[j];
                            if(1==roadLst[min][j])
                                curTeams+=numOfCity[j];
                        }
                        curTeams+=numOfCity[min];
                        if(curTeams>preTeams)
                        {
                            int visited=roadLst[road[i][1]][n+2];
                            roadLst[road[i][1]]=roadLst[min];
                            roadLst[road[i][1]][min]=1;
                            roadLst[road[i][1]][n+1]+=road[i][2];
                            roadLst[road[i][1]][n+2]=visited;
                        }
                        roadLst[road[i][1]][n]=sumOfRoad;
                    }
                }
            }
        }
    }
    int teams=0;
    for(int j=0;j!=n;++j)
    {
        if(1==roadLst[c2][j])
            teams+=numOfCity[j];
    }
    teams+=numOfCity[c2];
    cout<

你可能感兴趣的:(甲级-1003 Emergency (25 分))