题目大意:给出n,m,s,t,n表示有n个点,m表示有m条边,然后给出m行数据表示m条边,每条边的数据有连接两点的序号以及该边的权值,问说从点s到点t的最短路径是多少。
解题思路:本题应该是无环正权值的一个图,并且本题如果直接用Dijkstra算法去做的话超时,所以一定要用优先队列去进行优化,《算法竞赛入门经典》中介绍了这种写法,唯一变动的地方就是有向图变成了无向图。
#include <stdio.h> #include <string.h> #include <queue> #include <vector> using std::make_pair; using namespace std; const int N = 400005; const int INF = 1 << 30; typedef pair<int, int> pii; int n, m, s, t; int d[N], rec[N]; int first[N], u[N], next[N], v[N], w[N]; struct cmp { bool operator () (const int a, const int b) { return a % 10 > b % 10; } }; priority_queue<pii, vector<pii>, greater<pii> > q; void init() { scanf("%d%d%d%d", &n, &m, &s, &t); for (int i = 0; i < n; i++) first[i] = -1; int a, b; m *= 2; for (int i = 0; i < m; i++) { scanf("%d%d%d", &u[i], &v[i], &w[i]); next[i] = first[u[i]]; first[u[i]] = i; i++; v[i] = u[i - 1], u[i] = v[i - 1], w[i] = w[i - 1]; next[i] = first[u[i]]; first[u[i]] = i; } } void dijkstra() { bool rec[N]; for (int i = 0; i < n; i++) d[i] = (i == s ? 0 : INF); memset(rec, 0, sizeof(rec)); q.push(make_pair(d[s], s)); while (!q.empty()) { pii f = q.top(); q.pop(); int x = f.second; if (rec[x]) continue; rec[x] = 1; for (int e = first[x]; e != -1; e = next[e]) { if (d[v[e]] > d[x] + w[e]) { d[v[e]] = d[x] + w[e]; q.push(make_pair(d[v[e]], v[e])); } } } } int main () { int cas, ti = 1; scanf("%d", &cas); while (cas--) { init(); dijkstra(); printf("Case #%d: ", ti++); if (d[t] == INF) printf("unreachable "); else printf("%d ", d[t]); } return 0; }