PAT 甲级 1003(Emergency)

题目要求

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 C1 and C 2 C_2 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 c 1 c_1 c1, c 2 c_2 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 C 1 C_1 C1 to C 2 C_2 C2

Output Specification:
For each test case, print in one line two numbers: the number of different shortest paths between C 1 C_1 C1 and C 2 C_2 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

翻译

题意是求图中两个顶点的之间的最短路径问题,但是可能最短路径不止一条,输出最短路径的条数。然后在众多最短路径中,选择中途能聚集的医疗团队个数最多的那条,输出聚集的医疗个数。

代码

#include<iostream>
#include<vector>
#include<string.h>
using namespace std;
#define maxsize 500
int Graph[maxsize][maxsize];
int flag[maxsize]={0},dis[maxsize];
int cur_num[maxsize]={0};
int n,m,cur,des;//城市个数,路径,目前所在城市,目标城市
const int INF=0x3f3f3f;//定义一个很大的数
vector<int> vec[maxsize];//定义容器,存放到达当前站点的最大医疗数
void input()
{
    int x,y,z;//站点1,站点2,两者路径长度
    cin >> n>>m>>cur>>des;
    memset(Graph,-1,sizeof(Graph));
    for(int i=0;i<n;i++)
    {
        dis[i]=maxsize;//将路径长度设为最大
    }
    for(int i=0;i<n;i++)
    {
        cin>>cur_num[i];
    }
    for(int i=0;i<m;i++)
    {
        cin>>x>>y>>z;
        Graph[x][y]=z;
        Graph[y][x]=z;
    }
}
void push(int target,int dataid)//
{
    for(int i=0;i<vec[dataid].size();i++)
    {
        vec[target].push_back(vec[dataid][i]+cur_num[target]);
    }
}
void Dij(int source,int destination)
{
    flag[source]=1;//初始化访问
    dis[source]=0;//初始化距离为0
    vec[source].push_back(cur_num[source]);//存放站点医疗数量
    while(1)
    {//找到当前点相邻的点并且未访问
        for(int i=0;i<n;i++)
        {
            if(flag[i]==0&&Graph[source][i]!=-1)
            {
                if(dis[source]+Graph[source][i]<dis[i])
                {
                    dis[i]=dis[source]+Graph[source][i];
                    vec[i].clear();//清空
                    push(i,source);
                }
                else if(dis[source]+Graph[source][i]==dis[i])
                {
                    push(i,source);
                }
            }
        }
        //找下一个节点
        int min=INF;
        for(int i=0;i<n;i++)
        {
            if(flag[i]==0&&min>dis[i])
            {
                source=i;
                min=dis[i];
            }
        }
        flag[source]=1;
        if(source==destination) break;
    }

}
int main()
{
    input();
    if(n==0)//如果没有城市,走啥走,0输出
    {
        cout<<"0 0"<<endl;
    }
    else if(cur==des)//如果起始和终点是同一个输出1和该点医疗数量
    {
        cout<<"1 "<<cur_num[cur];
    }
    else
    {
        Dij(cur,des);
        vector<int> tt=vec[des];
        cout<<tt.size()<<" ";
        int num=tt[0];
        for(int i=0;i<tt.size();i++)
        {
            if(num<tt[i]) num=tt[i];
        }
        cout<<num;
    }
    return 0;
}

思路

很显然的一道图论的题目,这里使用Dijkstra算法,不过要加以改变,算出多条最短路径,另外要对经过点上的医疗队伍累加。
之前数学建模是用python库做的图论,而且有相关的函数解题,真是被惯坏了,还是第一次正儿八经的用C写图论算法,还是比较难上手的。具体的我在代码上进行了注释,在此就不赘述啦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值