Codeforces Beta Round #77 (Div. 1 Only) C. Volleyball (最短路)

题目链接: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;
}


原文地址:https://www.cnblogs.com/wally/p/4477066.html