今天给大家讲路径这道题目
题目描述
有n个点,m条无向边,有A,B两个人,初始时刻A在点1,B在点2,他们要走到点n去。A每走一条边,要消耗B单位能量,B每走一条边,要消耗E单位能量。如果A,B相伴走,则只消耗P单位的能量。请问A,B走到点n,最少要消耗多少能量?
输入数据保证1和n,2和n连通。
输入格式
输入:第一行包含整数B,E,P,N和M,所有的整数都不超过40000,N>=3.
接下来M行,每行两个整数,表示该无向边连接的两个顶点。
输出格式
一个整数,表示最小要消耗的能量
样例
样例输入
4 4 5 8 8
1 4
2 3
3 4
4 7
2 5
5 6
6 8
7 8
样例输出
22
思路
这个题一看就是一个图论里面的题目 这个题由于边数为
20000
20000
20000,点数为
20005
20005
20005 所以肯定不可以运用邻接矩阵来储存 只能用邻接表。
我们可以先用广搜把 从
a
,
b
,
n
a,b,n
a,b,n这三个点到任意一点的距离求出来 然后枚举那个他们开始相伴走的点 一个一个枚举 最后取一个最小值即可
代码
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int b,e,p;
int n,m;
//邻接表
struct path
{
int u,nxt;
}arr[80005];
int fst[80005];
//
int vis1[80005],vis2[80005],vis3[80005];//1,2,3分别储存从a,b,n这三个点出发到达其他点的最小花费
int vis[80005];//用于标记一个点是否被走过
int cnt;
queue<int> s;//储存点
queue<int> q;//储存路径
int ans=40005*40005;
void bfs(int k1,int dis[])//广搜
{
memset(vis,0,sizeof(vis));
vis[k1]=1;
s.push(k1);
q.push(0);
dis[k1]=0;
while(!s.empty())
{
int x=s.front();
int y=q.front();
s.pop();
q.pop();
dis[x]=y;
for(int j=fst[x];j;j=arr[j].nxt)
{
if(vis[arr[j].u]==0)//判断这个点是否被走过
{
vis[arr[j].u]=1;
s.push(arr[j].u);//把点推进队列
q.push(y+1);//把路径长度推进队列
}
}
}
}
void adds(int r,int l)
{
arr[++cnt].u=l,arr[cnt].nxt=fst[r],fst[r]=cnt;//储存进邻接表的操作
}
int x,y;
int main()
{
cin>>b>>e>>p>>n>>m;
for(int i=1;i<=m;++i)
{
cin>>x>>y;
adds(x,y);
adds(y,x);
}//输入
for(int i=1;i<=n;++i)
{
vis1[i]=10000000;
vis2[i]=10000000;
vis3[i]=10000000;//分别给vis1,vis2,vis3 赋值
}
bfs(1,vis1);
bfs(2,vis2);
bfs(n,vis3);
//将三个点分别广搜
for(int i=1;i<=n;++i)
{
if(vis1[i]==10000000||vis2[i]==10000000||vis3[i]==10000000)
continue;
ans=min(vis1[i]*b+vis2[i]*e+vis3[i]*p,ans);//一个一个枚举 取出最小值
}
cout<<ans<<endl;//输出答案
}