当前位置: 代码迷 >> 综合 >> USACO2010 驮运
  详细解决方案

USACO2010 驮运

热度:20   发布时间:2023-12-16 00:37:00.0

此题为一道SPFA的水题,对于不同的起点我们可以求出以其为源点的最短路,之后枚举每一点三段距离之和即可。

#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
typedef long long ll;
const int M=4e4+5;
const int inf=~0u>>1;
ll b,e,p,n,m,top=0;
int f[M];
ll fb[M],fe[M],fn[M];
struct edge{int nex,to;
}a[M*4];
inline void add(int u,int v){a[++top]=(edge){f[u],v};f[u]=top;
}
inline void init(){for(int i=1;i<=n;++i)fb[i]=fe[i]=fn[i]=inf;fb[1]=fe[2]=fn[n]=0;
}
bool inq[M];
queue<int> q1;
void spfa(int x){bool flag;memset(inq,false,sizeof(inq));q1.push(x);inq[x]=1;while(!q1.empty()){int u=q1.front();for(int i=f[u];i;i=a[i].nex){int v=a[i].to;flag=false;if(x==1){if(fb[v]>fb[u]+1)fb[v]=fb[u]+1,flag=true;}else if(x==2){if(fe[v]>fe[u]+1)fe[v]=fe[u]+1,flag=true;}else if(x==n){if(fn[v]>fn[u]+1)fn[v]=fn[u]+1,flag=true;}if(flag){if(!inq[v]){inq[v]=1;q1.push(v);}}}q1.pop();inq[u]=0;}
}
int main(){scanf("%lld%lld%lld%lld%lld",&b,&e,&p,&n,&m);int x,y;for(int i=1;i<=m;++i){scanf("%d%d",&x,&y);add(x,y);add(y,x);}init();spfa(1);spfa(2);spfa(n);ll ans=inf;for(int i=1;i<=n;++i) //printf("%lld %lld %lld\n",fb[i],fe[i],fn[i]);ans=min(ans,fn[i]*p+fb[i]*b+fe[i]*e);printf("%lld",ans);return 0;
}