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​​ 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,C1,C2 N为城市数目(编号为0—N-1),M为直接路径数目,C1为起始点C2为终点,第二行为N个城市的物资数目,接下来的M行分别为路径起点c1,c2,路径长度,

求出从C1到C2的最短路径数目,以及募得到最大物资

方法一:

思路:求图的路径问题,两个定点之间的最短路径,学习图的算法

求两个顶点之间的最短路径问题,初步考虑了dijkstra算法,但是未解决路径条数输出问题

重新学习dijkstra算法,详见dijkstra算法篇

参考原文http://kakazai.cn https://blog.csdn.net/yeziand01/article/details/80716688将答案重新整理,参考代码如下

#include<cstdio>
#include<algorithm>
using namespace std;
#define wq 10000000
const int maxN = 510;
int N,M,C1,C2;//N城市数目即顶点数目;M公路数目即边的条数;C1源点;C2终点
int Vscoure[maxN];//每个城市资源数目即顶点的权值
int Edge[maxN][maxN];//存储边的信息
int Pathlength[maxN];//源点到该点的路径长度
int Pathcount[maxN];//源点到该点的路径条数
int Maxscoure[maxN];//最大资源数
int Vflag[maxN];//顶点v是否被访问过
void Dijkstra(){//
for(int i=0;i<maxN;i++){//初始化所有路径为无穷大
    Pathlength[i]=wq;
}
Pathlength[C1]=0;//源点到自身的路径长度为0
 Pathcount[C1]=1;//源点到自身的路径数目为1
  Maxscoure[C1]=Vscoure[C1];//源点可募集最大资源为本身资源
  while(1){
        /*找出本轮尚未确定最短路径的城市中,起点到剩余城市中,距离最小Minlength的那个城市MinVertex。
如果Minlength是无穷大,证明起点城市与剩余城市均不可达,即不连通;
如果MinVertex就是目标城市C2,则表明已经确定起点城市到目标城市的最短路径,提前结束寻找。
否则,将本轮能确定最短路径的城市MinVertex设为已经处理好,Vflag[MinVertex]=1;
*/
//printf("---%d----\n",Pathcount[C2]);
    int Minlength = wq ,MinVertex = -1;

for(int i=0;i<N;i++){

    if(Vflag[i] == 1) continue;
    if (Pathlength[i] < Minlength) {
                Minlength = Pathlength[i];
                MinVertex = i;
            }
}
if(Minlength == wq||MinVertex == C2){
     //printf("minmin\n");
    break;
}
 Vflag[MinVertex] = 1;
 /*尝试从起点城市-城市MinVertex-其他城市i,如果路径更短,则更新;*/
for(int i =0;i<N;i++){
/*如果城市i已经处理好,或者城市MinVertex到不了城市i,则跳过;*/
    if(Vflag[i]==1||Edge[MinVertex][i]==0) continue;

    int templ = Pathlength[MinVertex]+Edge[MinVertex][i];
    int temph = Maxscoure[MinVertex]+ Vscoure[i];
    if(templ < Pathlength[i]){
        //printf("aabbccdd\n");
        Pathlength[i] = templ;
        Maxscoure[i] = temph;
        Pathcount[i] = Pathcount[MinVertex];
    }
    /*如果从城市mini过去城市i的路径更短,则更新所有属性*/

    else if(templ == Pathlength[i]){
    Pathcount[i] += Pathcount[MinVertex];
    if(temph > Maxscoure[i]){
        Maxscoure[i] = temph ;
    }
    /*如果从城市MinVertex到城市i的路径跟之前的路径距离相同,则更新最短路径数。但资源更多,即点权更大,则更新最多人手数*/

    }
}

  }
}

int main(){
    //按照题目要求输入
scanf("%d %d %d %d",&N,&M,&C1,&C2);
for(int i=0;i<N;i++)
scanf("%d",&Vscoure[i]);
for(int j=0;j<M;j++)
{
    int c1,c2,length;
    scanf("%d %d %d",&c1,&c2,&length);
    Edge[c1][c2]=Edge[c2][c1]=length;

}

Dijkstra();
printf("%d %d",Pathcount[C2],Maxscoure[C2]);

}
遇图 到的瓶颈:1.最近心态优点浮躁没有好好学习

2.对图的算法不能灵活应用,重新学习算法耗费了一点时间,仍然不是很深入所以没有灵活应用最终还是参考借鉴别人的思路

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值