PAT甲級1003 Emergency (25 分)題解

在這裏插入圖片描述在這裏插入圖片描述
\quad這是一個最短路的題,但要求多了一些,要求我們統計最短路條數,若有多條最短路,需要輸出能獲得營救隊伍最多的值。故需要我們在最憂子結構裏面更新兩個變量。我用num[v]表示起點s到點v最短路徑的條數,res[v]表示起點s到v點所能得到的最多隊伍數,故在初始化時候num[s]=1,res[s]=a[s],a[s]表示s點營救隊伍數量。最優子結構如下:

if(dis[v]>dis[u]+w)
{
	dis[v] = dis[u]+w;
	num[v] = num[u];
	res[v] = res[u]+a[v];
}
else if(dis[v]==dis[u]+w)
{
	num[v] += num[u];
	res[v] = max(res[v], res[u]+a[v]);
}

\quad總程序如下:

#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
const int maxn = 501;
int a[maxn];  // 記錄每個點營救隊伍數目
vector<pair<int, int> > E[maxn];
int vis[maxn], dis[maxn];
int num[maxn], res[maxn];
void dijstra(int s, int t)
{
	fill(dis, dis+maxn, 0x3f3f3f3f);
	dis[s] = 0;
	num[s] = 1;
	res[s] = a[s];
	priority_queue<pair<int, int> > q;
	q.push(make_pair(0, s));
	while(!q.empty())
	{
		int u = q.top().second;
		q.pop();
		if(vis[u]==1) continue;
		vis[u] = 1;
		for (int i = 0; i < E[u].size(); ++i)
		{
			int v = E[u][i].first, w = E[u][i].second;
			if(dis[v]>dis[u]+w)
			{
				dis[v] = dis[u]+w;
				num[v] = num[u];
				res[v] = res[u]+a[v];
				if(vis[v]==0) q.push(make_pair(-dis[v], v));
			}
			else if(dis[v]==dis[u]+w)
			{
				num[v] += num[u];
				res[v] = max(res[v], res[u]+a[v]);
				if(vis[v]==0) q.push(make_pair(-dis[v], v));
			}
		}
	}
	cout << num[t] << " " << res[t];
}
int main(int argc, char const *argv[])
{
	int N, M, s, t;
	cin >> N >> M >> s >> t;
    for(int i = 0; i < N; i++) cin >> a[i];
    while(M--)
    {
    	int u, v, w;
    	cin >> u >> v >> w;
    	E[u].push_back(make_pair(v, w));
    	E[v].push_back(make_pair(u, w));
    }
    dijstra(s, t);
	return 0;
}

\quad這裏也給出用spfa求解的程序,需注意的是spfa可能會重複訪問一個點,因此在統計最短路徑條數的時候需要額外用一個set進行存儲和去重的工作。

#include <iostream>
#include <vector>
#include <cstring>
#include <queue>
#include <set>
using namespace std;

const int maxn = 1001;
vector<pair<int, int> > E[maxn];
int teams[maxn];
int pathNum[maxn], teamNum[maxn];
int inq[maxn], dis[maxn];
set<int> st[maxn];
void spfa(int s, int t)
{
	fill(dis, dis+maxn, 0x3f3f3f3f);
	dis[s] = 0;
	queue<int> q;
	q.push(s);
	inq[s] = 1;
	pathNum[s] = 1;
	teamNum[s] = teams[s];
	while(!q.empty())
	{
		int u = q.front();
		q.pop();
		inq[u] = 0;
		for (int i = 0; i < E[u].size(); ++i)
		{
			int v = E[u][i].first, w = E[u][i].second;
			if(dis[v]>dis[u]+w)
			{
				dis[v] = dis[u]+w;
				pathNum[v] = pathNum[u];
				teamNum[v] = teamNum[u]+teams[v];
				st[v].clear();
				st[v].insert(u);
				if(inq[v]==0) q.push(v), inq[v]=1;
			}
			else if(dis[v]==dis[u]+w)
			{
				st[v].insert(u);
				pathNum[v] = 0;  // //因爲spfa會重複到一個點 所以可能重複的邊
				for(set<int>::iterator it=st[v].begin(); it!=st[v].end(); it++) pathNum[v] += pathNum[*it];
				teamNum[v] = max(teamNum[v], teamNum[u]+teams[v]);
				if(inq[v]==0) q.push(v), inq[v]=1;
			}
		}
	}
	cout << pathNum[t] << " " << teamNum[t];
}
int main(int argc, char const *argv[])
{
	int N, M, s, t;
	cin >> N >> M >> s >> t;
    for(int i = 0; i < N; i++) cin >> teams[i];
    while(M--)
    {
    	int u, v, w;
    	cin >> u >> v >> w;
    	E[u].push_back(make_pair(v, w));
    	E[v].push_back(make_pair(u, w));
    }
    spfa(s, t);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章