CodeForces - 95C Volleyball(建边+dij)
题意:n个路口m条边,每一个路口都有一辆出租车,给你每辆出租车的能经过的最大长度和花费,给你一个起点一个终点问你从起点到终点最少要多少钱。
题解:先用dij跑出每个点到另外点的最小距离,再枚举两个点的连线,如果满足d[i][j]<=i点出租车的最大长度则建边,最后再跑一次自己建的图
#include <iostream> #include <cstdio> #include <algorithm> #include <map> #include <queue> #define se second #define fi first #define Pli pair<ll,int> #define fio ios::sync_with_stdio(false);cin.tie(0) const int N=1e6+5e3; const ll INF=0x3f3f3f3f3f3f3f3f; using namespace std; int head[N]; int to[N]; ll val[N]; int nx[N]; ll dis[1005][1005]; int tot=1; void add(int u,int v,ll w){ to[tot]=v; val[tot]=w; nx[tot]=head[u]; head[u]=tot++; } priority_queue<Pli,vector<Pli>,greater<Pli> >q; int n,m; bool done[N]; ll len[N],c[N]; ll ans[N]; void dij(int n,int x,ll *dis ){ for(int i=1;i<=n;i++)dis[i]=INF,done[i]=0; dis[x]=0;q.push({0,x}); while(!q.empty()){ Pli p=q.top(); q.pop(); int u=p.se; ll dd=p.fi; for(int i=head[u];i;i=nx[i]){ int v=to[i]; if(dis[v]>dd+val[i]){ dis[v]=dd+val[i]; q.push({dis[v],v}); } } } } int main(){ scanf("%d %d",&n,&m); int s,t; scanf("%d %d",&s,&t); while(m--){ int u,v; ll w; scanf("%d%d%lld",&u,&v,&w); add(u,v,w); add(v,u,w); } for(int i=1;i<=n;i++){ dij(n,i,dis[i]); } for(int i=1;i<=n;i++){ scanf("%lld%lld",&len[i],&c[i]); } tot=1; memset(head, 0,sizeof(head)); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(i==j)continue; else if(dis[i][j]<=len[i])add(i,j,c[i]); } } dij(n,s,ans); if(ans[t]!=INF)cout<<ans[t]<<endl; else cout<<-1<<endl; return 0; }