洛谷 P3110 [USACO14DEC]Piggy Back S
题目传送门
因为每条边的长度是相同的,所以用bfs就行.当背起来走不比分开更优时,分别跑bfs就行.
当更优时,处理出每个点到1,2,n的距离,然后更新答案.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int n,m,b,p,r,tot,head[400001],ans = 2099999999,dis1[400001],dis[400001],dis2[400001];
bool vis[400001];
struct kkk {
int to,next;
}e[80002];
inline void add(int x,int y) {
e[++tot].to = y;
e[tot].next = head[x];
head[x] = tot;
}
inline void bfs(int s) {
memset(dis,0x3f3f3f,sizeof(dis));
memset(vis,0,sizeof(vis));
queue<int> q;
vis[s] = 1;
q.push(s);
dis[s] = 0;
while(!q.empty()) {
int u = q.front();
q.pop();
vis[u] = 0;
for(int i = head[u];i; i = e[i].next) {
int v = e[i].to;
if(dis[v] > dis[u] + 1) {
dis[v] = dis[u] + 1;
if(!vis[v]) q.push(v);
}
}
}
}
inline void bfs1(int s) {
memset(dis1,0x2f,sizeof(dis1));
memset(vis,0,sizeof(vis));
queue<int> q;
vis[s] = 1;
q.push(s);
dis1[s] = 0;
while(!q.empty()) {
int u = q.front();
q.pop();
vis[u] = 0;
for(int i = head[u];i; i = e[i].next) {
int v = e[i].to;
if(dis1[v] > dis1[u] + 1) {
dis1[v] = dis1[u] + 1;
if(!vis[v]) q.push(v);
}
}
}
}
inline void bfs2(int s) {
memset(dis2,0x2f,sizeof(dis1));
memset(vis,0,sizeof(vis));
queue<int> q;
vis[s] = 1;
q.push(s);
dis2[s] = 0;
while(!q.empty()) {
int u = q.front();
q.pop();
vis[u] = 0;
for(int i = head[u];i; i = e[i].next) {
int v = e[i].to;
if(dis2[v] > dis2[u] + 1) {
dis2[v] = dis2[u] + 1;
if(!vis[v]) q.push(v);
}
}
}
}
int main() {
scanf("%d%d%d%d%d",&b,&r,&p,&n,&m);
for(int i = 1;i <= m; i++) {
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
if(p >= b + r) {
bfs(1);
ans = dis[n] * b;
bfs(2);
ans += dis[n] * r;
printf("%d",ans);
return 0;
}
bfs(1);
bfs1(2);
bfs2(n);
for(int i = 1;i <= n; i++)
ans = min(ans,dis1[i] * r + dis[i] * b + dis2[i] * p);
printf("%d",ans);
return 0;
}