PKU 3255 Roadblocks

  • k-th shortest pathという有名問題です
  • Spaghetti Sourceのライブラリを使用しています
static const int INF = INT_MAX / 2;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()

typedef int Weight;
struct Edge {
	int src, dst;
	Weight weight;
	Edge(int src, int dst, Weight weight) :
	src(src), dst(dst), weight(weight) { }
};
bool operator < (const Edge &e, const Edge &f) {
	return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
		e.src != f.src ? e.src < f.src : e.dst < f.dst;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

Weight k_shortestPath(const Graph &g, int s, int t, int k) {
	const int n = g.size();

	Graph h(n); // make reverse graph
	REP(u, n) {
		for (Edges::const_iterator e = g[u].begin(); e != g[u].end(); ++e) {
			h[e->dst].push_back(Edge(e->dst,e->src,e->weight));
		}
	}

	vector<Weight> d(n, INF); d[t] = 0; // make potential
	vector<int> p(n, -1);               // using backward dijkstra
	priority_queue<Edge> Q; Q.push(Edge(t, t, 0));
	while (!Q.empty()) {
		Edge e = Q.top(); Q.pop();
		if (p[e.dst] >= 0) continue;
		p[e.dst] = e.src;
		for (Edges::iterator f = h[e.dst].begin(); f != h[e.dst].end(); ++f) {
			if (d[f->dst] > e.weight + f->weight) {
				d[f->dst] = e.weight + f->weight;
				Q.push(Edge(f->src, f->dst, e.weight + f->weight));
			}
		}
	}
	int l = 0; // forward dijkstra-like method
	priority_queue<Edge> R; R.push(Edge(-1,s,0));
	while (!R.empty()) {
		Edge e = R.top(); R.pop();
		if (e.dst == t && ++l == k) return e.weight + d[s];
		for (Edges::const_iterator f = g[e.dst].begin(); f != g[e.dst].end(); ++f) {
			R.push(Edge(f->src, f->dst, e.weight+f->weight-d[f->src]+d[f->dst]));
		}
	}
	return -1; // not found
}

int main()
{
	int N, R;
	cin >> N >> R;
	Graph g(N + 1);
	for (int i = 0; i < R; ++i) {
		int A, B, D;
		cin >> A >> B >> D;
		g[A].push_back(Edge(A, B, D));
		g[B].push_back(Edge(B, A, D));
	}
	cout << k_shortestPath(g, 1, N, 2) << endl;
}