bzoj2100 [Usaco2010 DEC]Apple Delivery苹果贸易
题目描述
一张P个点的无向图,C条正权路。CLJ要从Pb点(家)出发,既要去Pa1点NOI赛场拿金牌,也要去Pa2点CMO赛场拿金牌。(途中不必回家)可以先去NOI,也可以先去CMO。当然神犇CLJ肯定会使总路程最小,输出最小值。
题解:做两遍spfa,找出从起点开始先去pa1或者先去pa2的最小值
需要用一下spfa的优化,每次进行入队的时候都与队头进行比较,如果比队头小就放在队头,否则放队尾。
#include<bits/stdc++.h> using namespace std; #define maxn 100005 #define maxm 200005 int dis[maxn],head[maxn],q[maxn]; bool vis[maxn]; struct edge{ int next,to,w; }e[maxm*2]; int n,m,s,t1,t2; int ans=2000000000,cnt; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void insert(int u,int v,int w){ cnt++; e[cnt].next=head[u];e[cnt].to=v;e[cnt].w=w; head[u]=cnt; } void spfa(int x){ memset(dis,127,sizeof dis); vis[x]=1;dis[x]=0;q[0]=x; int top=0,tail=1; while(top!=tail) { int now=q[top];top++; if(top==100001)top=0; for(int i=head[now];i;i=e[i].next){ int p=e[i].to; if(dis[p]>dis[now]+e[i].w){ dis[p]=dis[now]+e[i].w; if(!vis[p]){ vis[p]=1; if(dis[p]<dis[q[top]]){ top--;if(top<0)top=100000; q[top]=p; } else{ q[tail++]=p; if(tail==100001)tail=0; } } } } vis[now]=0; } } int main(){ m=read();n=read();s=read();t1=read();t2=read(); int u,v,w; for(int i=1;i<=m;i++){ u=read();v=read();w=read(); insert(u,v,w);insert(v,u,w); } spfa(t1); ans=dis[s]+dis[t2]; spfa(t2); ans=min(ans,dis[s]+dis[t1]); printf("%d",ans); }