BD202301·公园题解
BD202301·公园题解
考虑将整个移动过程分为两个部分:
- 小度和度度熊汇合之前
- 小度和度度熊汇合之后
第一部分可以直接用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;
}