洛谷P3110 [USACO14DEC]Piggy Back S(最短路问题)

题目地址https://www.luogu.com.cn/problem/P3110

题意

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

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

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

输入

第一行五个正整数,B,E,P,N(区域数),M(边数)

接下来M行,每行两个正整数,u,v表示两个区域之间存在一条边

输出:输出一个正整数,表示最小花费

题解:可以遍历每一个结点i,使得i是中转点,也就是二人在结点i汇合,然后再一起走。当i=n的时候,便包含了二者不一起走的情况。所以需要计算三次最短路,一个是Bessie的单源最短路,一个是Elsie的最短路,一个是终点到其余点的最短路。所以这个时候答案就是所有结点中最小的一个就是。每个结点是二人单独到这个结点的能量,然后加上这个结点到终点二者一起走的能量。

AC代码

#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio> 
using namespace std;
const int N=40000+5;
struct st{
    int from,to,next;
}edge[N*2];

 
int head[N],dis[3][N],b,e,p,n,m,cnt=0,vis[N];
void addedge(int u,int v){
    cnt++;
    edge[cnt].from=u;
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt;
}
void dijkstra(int s,int k){
    memset(dis[k],0x3f,sizeof(dis[k]));
    memset(vis,0,sizeof(vis));
    dis[k][s]=0;
    priority_queue<pair<int,int>,vector<pair<int,int> > ,greater<pair<int,int> > >q;
    q.push(make_pair(0,s));
    pair<int,int>pa;
    while(!q.empty()){
        pa=q.top();q.pop();
        if(vis[pa.second]==1) continue;
        vis[pa.second]=1;
        dis[k][pa.second]=pa.first;
        for(int i=head[pa.second];i;i=edge[i].next){
            if(vis[edge[i].to]==1) continue;
            q.push(make_pair(pa.first+1,edge[i].to));
        }
    }
}
int main(){
    cin>>b>>e>>p>>n>>m;
    for(int i=1,u,v;i<=m;i++){
    //    cin>>u>>v;
        scanf("%d%d",&u,&v);
        addedge(u,v);
        addedge(v,u);
    }
    dijkstra(1,0);
    dijkstra(2,1);
    dijkstra(n,2);
    int ans=0x3f3f3f3f;
    for(int i=1;i<=n;i++){
        ans=min(ans,dis[0][i]*b+dis[1][i]*e+dis[2][i]*p);
    }
    cout<<ans<<endl;
    return 0;
} 

写于2020/8/11 10:35

posted @ 2020-08-11 10:36  白菜茄子  阅读(173)  评论(0编辑  收藏  举报