http://codeforces.com/problemset/problem/95/C
n点m边(无向有权),每个点有一个司机(Ti,Ci)表示支付Ci元走Ti长度且必须停在节点才合法,一个司机只能使用最多一次,问从x-y最小花费。
n,m<=1000,预处理处任意两点最短距离,然后按照Ci建立新图,如果i点司机的Ti足够到达j那么就连边,最后在新图跑最短路。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define LL long long 4 #define mp make_pair 5 #define pb push_back 6 #define fi first 7 #define se second 8 #define pii pair<int,int> 9 #define inf 0x3f3f3f3f3f3f3f3f 10 const int maxn=1010; 11 vector<pii>g1[maxn],g2[maxn]; 12 LL d[maxn]; 13 int T[maxn],C[maxn]; 14 int n,m,x,y; 15 bool vis[maxn]; 16 void spfa(int st,LL d[],vector<pii> g[]){ 17 memset(vis,0,sizeof(vis)); 18 memset(d,inf,sizeof(LL)*(n+1)); 19 queue<int>q; 20 q.push(st); 21 vis[st]=1,d[st]=0; 22 while(!q.empty()){ 23 int u=q.front();q.pop();vis[u]=0; 24 for(auto e:g[u]){ 25 int v=e.fi,w=e.se; 26 if(d[v]>d[u]+w){ 27 d[v]=d[u]+w; 28 if(!vis[v])q.push(v),vis[v]=1; 29 } 30 } 31 } 32 } 33 34 int main(){ 35 int u,v,w; 36 cin>>n>>m>>x>>y; 37 while(m--){ 38 cin>>u>>v>>w; 39 g1[u].push_back(mp(v,w)); 40 g1[v].push_back(mp(u,w)); 41 } 42 for(int i=1;i<=n;++i)cin>>T[i]>>C[i]; 43 for(int i=1;i<=n;++i){ 44 spfa(i,d,g1); 45 for(int j=1;j<=n;++j){ 46 if(i==j || d[j]>T[i])continue; 47 g2[i].pb(mp(j,C[i])); 48 } 49 } 50 spfa(x,d,g2); 51 if(d[y]==inf)cout<<-1; 52 else cout<<d[y]<<' '; 53 return 0; 54 }