BD202301·公園題解

Boring__Zheng發表於2024-06-22

BD202301·公園題解

考慮將整個移動過程分為兩個部分:

  1. 小度和度度熊匯合之前
  2. 小度和度度熊匯合之後

第一部分可以直接用Dijkstra演算法直接搞定,第二部分可以考慮反向思考,從N點出發做一次Dijkstra, 最後列舉每個匯合點即可得到答案。

時間複雜度\(\Theta (nlogn)\)

程式碼如下:

#include <bits/stdc++.h>
using namespace std;

const int N = 400005;
struct Edge
{
	int ver, nxt;
}edge[N];
int head[N], tote;

void add(int x, int y)
{
	edge[++tote].ver = y;
	edge[tote].nxt = head[x];
	head[x] = tote;
}

inline int read()
{
	int x = 0; char ch = getchar();
	while (ch < '0' or ch > '9') ch = getchar();
	while (ch >= '0' and ch <= '9') x = x * 10 + ch - '0', ch = getchar();
	return x;
}

void Dijkstra(int* dis, int sta, int n)
{
	bool vis[N];
	for (int i = 1; i <= n; ++i) dis[i] = 0x7ffff, vis[i] = false;
	priority_queue < pair < int, int>> q;
	dis[sta] = 0;
	q.push(make_pair(0, sta));
	while(!q.empty())
	{
		int x = q.top().second;
		q.pop();
		if (vis[x]) continue;
		vis[x] = true;
		for (int i = head[x]; i; i = edge[i].nxt)
		{
			int y = edge[i].ver;
			if (dis[y] > dis[x] + 1)
			{
				dis[y] = dis[x] + 1;
				q.push(make_pair(-dis[y], y));
			}
		}
	}
}

int main()
{
	int TE = read(), FE = read(), S = read();
	int T = read(), F = read(), n = read(), m = read();
	for (int i  = 0; i < m; ++i)
	{
		int x = read(), y = read();
		add(x, y);
		add(y, x);
	}
	int dist[N], disf[N], disn[N];
	Dijkstra(dist, T, n);
	Dijkstra(disf, F, n);
	Dijkstra(disn, n, n);
	int ans = 0x7fffffff;
	for (int i = 1; i <= n; ++i)
		if (ans > dist[i] * TE + disf[i] * FE + disn[i] * (TE + FE - S)) ans = dist[i] * TE + disf[i] * FE + disn[i] * (TE + FE - S);
	if (disn[T] == 0x7ffff or disn[F] == 0x7ffff) cout << "-1";
	else cout << ans;
	return 0;
}

相關文章