一句话题意:
三个点a1,a2,b,求从b到a1和a2的最短路
做法:求出a1->b和a2->b的最短路,两者取min,之后再加上a1->a2的最短路
为啥呢
由于题目中说:没有路会从另一个牧场走回自己
所以图只有以下三种情况
emmmmmmm
懂了吗
另外注意裸的SPFA会TLE3个点,可以用SLF优化(有人说LLL会TLE4个……)
堆优化Dijkstra可以直接过
下面给出SPFA的代码和堆优化Dijkstra的代码
#include <queue> #include <cstdio> #include <cstring> #include <iostream> const int N=100001,M=200001; #define gc() (SS==TT &&(TT=(SS=IN)+fread(IN,1,1<<20,stdin),SS==TT)?EOF:*SS++) char IN[1<<20],*SS=IN,*TT=IN; int n,m,st,e1,e2,q[N+M],h[N]; struct Edge{ int u,v,w,nxt; }edge[M<<1]; bool vis[N]; int dis[N],num; inline int read() { int n=0,w=1;register char c=gc(); while(c>'9'||c<'0'){if(c=='-')w=-1;c=gc();} while(c>='0'&&c<='9')n=n*10+c-'0',c=gc(); return n*w; } inline void add(int u,int v,int w) { edge[++num].u=u; edge[num].v=v; edge[num].w=w; edge[num].nxt=h[u]; h[u]=num; } inline void SPFA(int s) { memset(dis,0x7f,sizeof dis); int head=0,tail=0; q[++tail]=s; dis[s]=0;vis[s]=true; while(head<tail) { int now=q[++head]; vis[now]=false; for(int v,i=h[now];i;i=edge[i].nxt) { v=edge[i].v; if(dis[v]>dis[edge[i].u]+edge[i].w) { dis[v]=dis[edge[i].u]+edge[i].w; if(!vis[v]) { vis[v]=true; if(dis[v]>dis[q[head+1]]||head==tail) q[++tail]=v; else q[head--]=v;//双端队列 } } } } } int main() { m=read(),n=read(),st=read(),e1=read(),e2=read(); for(int u,v,w,i=0;i<m;++i) { u=read(),v=read(),w=read(); add(u,v,w);add(v,u,w); } int ans1,ans2; SPFA(e1); ans1=dis[st]+dis[e2]; SPFA(e2); ans2=dis[st]+dis[e1]; printf("%d",std::min(ans1,ans2)); return 0; }