P3110 [USACO14DEC]驮运Piggy Back-最短路,spfa

版权声明:原创,勿转 https://blog.csdn.net/qq_42386465/article/details/82881545

Bessie 和 Elsie在不同的区域放牧,他们希望花费最小的能量返回谷仓。从一个区域走到一个相连区域,Bessie要花费B单位的能量,Elsie要花费E单位的能量。

如果某次他们两走到同一个区域,Bessie 可以背着 Elsie走路,花费P单位的能量走到另外一个相连的区域。当然,存在P>B+E的情况。

相遇后,他们可以一直背着走,也可以独立分开。

https://www.luogu.org/problemnew/show/P3110

Bessie和Elsie分别从1和2出发到n,如果某一点会相遇,可以选择剩下的路两个人一起走或者分开走。

因为只有一次相遇且不会一起走然后又分开,这样就对1,2,n三个点各跑一次最短路

最后枚举每一个点(相遇点)

ans=min(dis_b[i]*b+dis_e[i]*e+dis_n[i]*p);

相遇前b走过的路程*b+相遇前e走过的路程*e+一起走的路程*p;

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int maxn = 8e4+3;
int dis_b[maxn],dis_e[maxn],dis_n[maxn],head[maxn];
bool vis[maxn];
int cnt,b,e,p,n,m,ans=2147483647;
const int INF = 2147483647;
queue<int> q;
struct node
{
    int next,to;
}E[maxn*10];
void add(int x,int y)
{
    E[++cnt].next=head[x];
    E[cnt].to=y;
    head[x]=cnt;
}
void spfa(int s,int *dis)
{
    memset(vis,0,sizeof(vis));
    fill(dis+1, dis+1+n, INF);
    dis[s]=0;
    vis[s]=true;
    q.push(s);
    while(!q.empty()){
        int now=q.front();q.pop();vis[now]=false;
        for(int i=head[now];i;i=E[i].next){
            int to=E[i].to;
            if(dis[to]>dis[now]+1){
                dis[to]=dis[now]+1;
                if(!vis[to]){
                    q.push(to);
                    vis[to]=true;
                }
            }
        }
    }
}
int main()
{
    scanf("%d%d%d%d%d",&b,&e,&p,&n,&m);
    for(int i=1;i<=m;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }
    spfa(1,dis_b);spfa(2,dis_e);spfa(n,dis_n);
    for(int i=1;i<=n;i++){
        ans=min(ans,dis_b[i]*b+dis_e[i]*e+dis_n[i]*p);
    }
    printf("%d",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42386465/article/details/82881545