解题思路
看到下面很多人都在说什么遇到了之后要不要背着走,其实根本不需要,同样的我也是跑了三遍$SPFA$,求出了以$1$为起点到个点的$dist$,和以$2$为起点到个点的$dist$,还有以$n$为起点到个点的$dist$。
之后直接枚举两头牛在哪里相遇,相遇之后一起背着走的路程乘以$p+$相遇之前$B$走的距离乘以$b+$相遇之前$E$走的距离乘以$e$,去一个最小的这样的值就是答案。
关于为什么不需要分类讨论,因为你把每个点都枚举了一遍,即使存在$p>b+e$的情况,那这种情况就等价于两头奶牛在$n$点相遇。
附上代码
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <queue> const int maxn = 8e4+3, INF = 2147483647; int b, e, p, n, m, fir[maxn], nxt[maxn], u[maxn], v[maxn], cnt; int dist_n[maxn], dist_1[maxn], dist_2[maxn], w[maxn], Ans = INF; bool vis[maxn]; inline int read() { int x = 0, f = 1; char c; while (c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while (c <= '9' && c >= '0') {x = x*10 + c-'0'; c = getchar();} return x * f; } inline void addedge(int x, int y, int z) { nxt[++cnt] = fir[x]; fir[x] = cnt; u[cnt] = x, v[cnt] = y, w[cnt] = z; } inline void SPFA(int s, int *dist) { std::queue<int> Q; std::memset(vis, 0, sizeof(vis)); std::fill(dist+1, dist+1+n, INF); vis[s] = 1, dist[s] = 0; Q.push(s); int x, k; while (!Q.empty()) { x = Q.front(), Q.pop(); int k = fir[x]; while (k != -1) { if(dist[v[k]] > dist[u[k]] + w[k]) { dist[v[k]] = dist[u[k]] + w[k]; if(!vis[v[k]]) Q.push(v[k]); } k = nxt[k]; } vis[x] = 0; } } int main() { b = read(), e = read(), p = read(), n = read(), m = read(); std::memset(fir, -1, sizeof(fir)); int x, y, z = 1; for(register int i=1; i<=m; i++) { x = read(), y = read(); addedge(x, y, z), addedge(y, x, z); } SPFA(1, dist_1), SPFA(2, dist_2), SPFA(n, dist_n); for(int i=1; i<=n; i++) Ans = std::min(Ans, dist_1[i] * b + dist_2[i] * e + dist_n[i] * p); printf("%d", Ans); }