洛谷:link
由题意我们可知,需要找出两只牛的汇合点,再求出此点到终点的最短路。
之后再将问题转化,分别以1、2、n点为源点,求三次SPFA,再将dis累加,最小值即为答案。
代码如下:
#include<stdio.h>
#include<queue>
#include<cstring>
using namespace std;
#define MAX 80001
int head[MAX],to[MAX],nxt[MAX];
int dis[MAX];
int ans[MAX];
bool inQ[MAX];
queue<int>q;
int tot=0;
int min(int x,int y)
{
return x<y?x:y;
}
void spfa(int s,int v)
{
memset(dis,0x3f3f,sizeof(dis));
dis[s]=0;
q.push(s);
inQ[s]=1;
while(!q.empty())
{
int p=q.front();
q.pop();
inQ[p]=0;
for(int i=head[p];i;i=nxt[i])
{
int y=to[i];
if(dis[y]>dis[p]+v)
{
dis[y]=dis[p]+v;
if(inQ[y]==0)
q.push(y),inQ[y]=1;
}
}
}
}
void add(int x,int y)
{
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
int main()
{
int b,e,p,n,m;
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,b);
for(int i=1;i<=n;i++)
ans[i]+=dis[i];
spfa(2,e);
for(int i=1;i<=n;i++)
ans[i]+=dis[i];
spfa(n,p);
int a=0x3f3f3f3f;
for(int i=1;i<=n;i++)
{
ans[i]+=dis[i];
a=min(ans[i],a);
}
printf("%d",a);
}