1. 程式人生 > 實用技巧 >pat 1003 Emergency

pat 1003 Emergency

題目連結:https://pintia.cn/problem-sets/994805342720868352/problems/994805523835109376

  1. 要看清楚到底是有向圖還是無向圖(建圖的時候要用)
  2. 用哪種方法求最短路
  3. 仔細考慮附帶問題(像本題中的最短路的個數,和在最短路條件下的最大營救人數)
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
struct edge{
	int u,v,w,next;
}e[1100];
int team[505], head[505], cnt, sum[505]; //c1-i最短路徑下的team數 
int n,m,c1,c2, dis[505];
int path_num[505];
bool vis[505];
void add(int a, int b, int c){//鄰接表存圖
	e[++cnt].u = a;
	e[cnt].v = b;
	e[cnt].w = c;
	e[cnt].next = head[a];
	head[a] = cnt;
}
void dijkstra(){ //優先佇列優化的dijkstra演算法
	for (int i = 0; i < n; i++){
		dis[i] = 1e9; vis[i] = false;
	}
	dis[c1] = 0; sum[c1] = team[c1]; path_num[c1] = 1;
	priority_queue<pair<int,int> > que;
	que.push(make_pair(0, c1));
	while (!que.empty()){
		int cur = que.top().second;
		//cout<<cur<<endl;
		que.pop();
		if (vis[cur]) continue;
		vis[cur] = true;
		for (int i = head[cur]; i; i = e[i].next){
			int now = e[i].v;
			if (vis[now]) continue;
			if (dis[cur]+e[i].w < dis[now]){
				dis[now] = dis[cur] + e[i].w;
				que.push(make_pair(-dis[now], now));
                path_num[now] = path_num[cur];//如果最短路更新,那麼path_num和sum都要重新賦值
				sum[now] = sum[cur]+team[now];
			}else if (dis[cur]+e[i].w == dis[now]){
				path_num[now] += path_num[cur];
				sum[now] = max(sum[now], sum[cur]+team[now]);
			}
			
		}
	}
}
int main()
{
	cin>>n>>m>>c1>>c2;
	for (int i = 0; i < n; i++) cin >> team[i];
	for (int i = 0; i < m; i++){
		int a,b,c;
		cin>>a>>b>>c;
		add(a, b, c);
		add(b, a, c); //這裡要進行雙邊儲存、又因為是雙向建邊,因為edge要開點的兩倍多一點
	}
	dijkstra();
	cout<<path_num[c2]<<" "<<sum[c2];
	return 0;
}