PAT - 甲级 - 1003 - Emergency

Nothing to fear


种一棵树最好的时间是十年前,其次是现在!

那些你早出晚归付出的刻苦努力,你不想训练,当你觉的太累了但还是要咬牙坚持的时候,那就是在追逐梦想,不要在意终点有什么,要享受路途的过程,或许你不能成就梦想,但一定会有更伟大的事情随之而来。 mamba out~

2020.7.13


人一我十,人十我百,追逐青春的梦想,怀着自信的心,永不言弃!

Emergency

分析

在Dijkstar得基础上记录到达某个点得最短路径得条数,以及点权最大值的方法

  1. 记录最短路条数

    记录路径条数得方法: 设置一个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];
}
  1. 记录最大点权

    我们设置一个数组 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;
}
posted @ 2020-07-13 19:01  _starsky  阅读(120)  评论(0编辑  收藏  举报