PAT - 甲级 - 1003 - Emergency
Nothing to fear
种一棵树最好的时间是十年前,其次是现在!
那些你早出晚归付出的刻苦努力,你不想训练,当你觉的太累了但还是要咬牙坚持的时候,那就是在追逐梦想,不要在意终点有什么,要享受路途的过程,或许你不能成就梦想,但一定会有更伟大的事情随之而来。 mamba out~
2020.7.13
人一我十,人十我百,追逐青春的梦想,怀着自信的心,永不言弃!
Emergency
分析
在Dijkstar得基础上记录到达某个点得最短路径得条数,以及点权最大值的方法
-
记录最短路条数
记录路径条数得方法: 设置一个num数组,令num[strat] = 1;
1.1 当在某个点x - > y 满足 dis[y] > dis[x] + w (w 表示 x- > y 得边权)
此时需要更新最短路所以 num[y] = num[x]
if(dis[y] > dis[x] + w)
{
num[y] = num[x];
}
1.2 当在某个点x - > y 满足 dis[y] == dis[x] + w (w 表示 x- > y 得边权)
此时到达 y 得最短路径条数等于先前到达 y 得路径条数 + 到达 x 点得路径条数
即 num[y] = num[y] + num[x]
if(dis[y] == dis[x] + w)
{
num[y] = num[x] + num[y];
}
-
记录最大点权
我们设置一个数组 w 来记录到达每个点得可以携带得最大点权时多少
首先令w[start] = weight[start]
2.1 当在某个点x - > y 满足 dis[y] > dis[x] + w (w 表示 x- > y 得边权)
if(dis[y] > dis[x] + w)
{
num[y] = num[x];
w[y] = w[x] + weight[y]; // 直接更新w[y]
}
2.2 当在某个点x - > y 满足 dis[y] == dis[x] + w (w 表示 x- > y 得边权)
if(dis[y] == dis[x] + w)
{
num[y] = num[x] + num[y];
w[y] = max(w[y] , w[x] + wight[y]) // 取得所有最短路径中可携带点权最大得那一个
}
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
const int N = 25005;
struct edge{
int to, next, w;
}e[N];
int head[N] , tot = 1, weight[N];
bool vis[N];
int n , m , s , t;
int dis[N] , ans[N] , num[N];
void add(int a, int b, int w)
{
e[tot].w = w;
e[tot].to = b;
e[tot].next = head[a];
head[a] = tot++;
}
void Dijkstra(int s)
{
memset(dis , 0x3f , sizeof dis);
memset(vis , 0 , sizeof vis);
dis[s] = 0;ans[s] = weight[s];num[s] = 1;
// 首先找到一个距离最短的点放入集合中
for(int k = 0;k < n - 1;k ++)
{
int x = -1;
for(int i = 0;i < n;i ++)
{
if(!vis[i] && (x == -1 || dis[i] < dis[x]))
x = i;
}
if(x == -1)break;
vis[x] = 1;
for(int i = head[x]; i ;i = e[i].next)
{
int y = e[i].to, w = e[i].w;
if(vis[y])continue;
if(dis[y] > dis[x] + w)
{
dis[y] = dis[x] + w;
num[y] = num[x];
ans[y] = ans[x] + weight[y];
}
else if(dis[y] == dis[x] + w)
{
num[y] = num[y] + num[x];
ans[y] = max(ans[y],ans[x] + weight[y]);
}
}
}
}
int main()
{
cin >> n >> m >> s >> t;
for(int i = 0;i < n ;i ++)
scanf("%d",&weight[i]);
int a , b , c;
for(int i = 0;i < m;i ++)
{
scanf("%d %d %d",&a , &b , &c);
add(a , b , c);add(b , a , c);
}
Dijkstra(s);
cout << num[t] << " " << ans[t] << endl;
return 0;
}