题目地址: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