P3110 [USACO14DEC]Piggy Back S 題解
阿新 • • 發佈:2020-11-17
Description
給出一個無向圖,Bessie從1號倉庫走到n號(每次花費B), Elsie從2號倉庫走到n號(每次花費E),如果兩個人走同一條路花費P,求總花費最小。
輸入B,E,P,n,m和m條邊的聯通情況。
輸出最少花費。
SimpleInput
4 4 5 8 8
1 4
2 3
3 4
4 7
2 5
5 6
6 8
7 8
SimpleOutput
22
資料範圍
\(1\le n,m,b,e,p\le 4×10^4,n \ge 3\)
Solution
首先這道題明顯是一個最短路,和在一起考慮有一點麻煩,所以我們分開考慮。
對於 Bessie 和 Elsie 來說,他們走到任意一個點的最短路是非常好算的。假設他們現在都走到了點 \(i\)
時間複雜度為 \(\mathcal{O(k\times n)}\) (SPFA 時間複雜度)
Code
#include <bits/stdc++.h> using namespace std; const int N = 100007; int dis[4][N],inq[4][N],head[N]; int m,n,u,v,b,e,p,cnt = 0,ans = 2147483647; struct node { int v,nxt; node() {} node(int _v,int _nxt) { v = _v; nxt = _nxt; } }E[N]; template <class T> inline void read(T &x) { x = 0; int p = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') p = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } x = x * p; } void add_edge(int u,int v) { E[++cnt] = node(v,head[u]); head[u] = cnt; } void spfa(int id,int st) { //SPFA int wi; if(id == 1) wi = b; if(id == 2) wi = e; if(id == 3) wi = p; queue <int> q; memset(dis[id],0x3f,sizeof(dis[id])); memset(inq[id],0,sizeof(inq[id])); dis[id][st] = 0; inq[id][st] = 1; q.push(st); while(!q.empty()) { int u = q.front(); q.pop(); inq[id][u] = 0; for(int i = head[u];i != 0;i = E[i].nxt) { int v = E[i].v; if(dis[id][v] > dis[id][u] + wi) { dis[id][v] = dis[id][u] + wi; if(!inq[id][v]) { inq[id][v] = 1; q.push(v); } } } } } int main() { read(b); read(e); read(p); read(n); read(m); for(int i = 1;i <= m;i++) { read(u); read(v); add_edge(u,v); add_edge(v,u); } spfa(1,1); spfa(2,2); spfa(3,n); // 1表示Bessie,2表示Elsie,3表示他們一起走 for(int i = 1;i <= n;i++) { ans = min(ans,dis[1][i] + dis[2][i] + dis[3][i]);//取最小值 } printf("%d\n",ans); return 0; }