题目链接:http://codeforces.com/contest/95/problem/C
思路:首先dijkstra预处理出每个顶点到其他顶点的最短距离,然后如果该出租车到某个顶点的距离小于等于最短距离,就连边,费用为一开始出租车所需的费用,建好图之后再求一次最短路即可。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <queue> #define REP(i, a, b) for (int i = (a); i < (b); ++i) #define FOR(i, a, b) for (int i = (a); i <= (b); ++i) using namespace std; const int MAX_N = (1000 + 100); const long long inf = 1LL << 60; int N, M, st, ed, vis[MAX_N][MAX_N]; long long dist[MAX_N][MAX_N], cost[MAX_N]; /* struct cmp { bool operator () (const pair<long long, int> &p, const pair<long long, int> &q) const { return p.first > q.first; } };*/ vector<int > from[MAX_N]; vector<pair<int, int> > g[MAX_N]; void Dijkstra(int s) { priority_queue<pair<long long, int>, vector<pair<long long, int> >, less<pair<long long, int> > > pq; pq.push(make_pair(-(dist[s][s] = 0), s)); while (!pq.empty()) { pair<long long, int > p = pq.top(); pq.pop(); if (vis[s][p.second]) continue; vis[s][p.second] = 1; for (vector<pair<int, int > >::const_iterator it = g[p.second].begin(); it != g[p.second].end(); ++it) { if (-(p.first) + it->second < dist[s][it->first]) { dist[s][it->first] = -(p.first) + it->second; if (!vis[s][it->first]) { pq.push(make_pair(-(dist[s][it->first]), it->first)); } } } } } long long dp[MAX_N]; int mark[MAX_N]; long long getDp() { FOR(i, 1, N) dp[i] = inf, mark[i] = 0; dp[st] = 0; queue<int > que; que.push(st); while (!que.empty()) { int u = que.front(); que.pop(); mark[u] = 0; REP(i, 0, (int)from[u].size()) { int v = from[u][i]; if (dp[u] + cost[u] < dp[v]) { dp[v] = dp[u] + cost[u]; if (!mark[v]) { mark[v] = 1; que.push(v); } } } } if (dp[ed] >= inf) return -1; return dp[ed]; } int main() { cin >> N >> M >> st >> ed; FOR(i, 1, M) { int u, v, w; cin >> u >> v >> w; g[u].push_back(make_pair(v, w)); g[v].push_back(make_pair(u, w)); } FOR(i, 1, N) { FOR(j, i, N) dist[j][i] = dist[i][j] = inf, vis[j][i] = vis[i][j] = 0; } FOR(i, 1, N) Dijkstra(i); FOR(i, 1, N) { int t, c; cin >> t >> cost[i]; FOR(j, 1, N) if (j != i && dist[i][j] <= t) { from[i].push_back(j); } } cout << getDp() << endl; return 0; }