理想路径 Ideal Path NEERC 2010 UVa1599

【分析】
本题只是一个普通的最短路问题,可以用BFS解决。但是“记录父结点”的方法已经不适用了,因为这样打印出来的路径并不能保证字典序最小。
事实上。无须记录父结点也能得到最短路,方法是从终点开始“倒着”BFS,得到每个结点i到终点的最短距离d[i],然后直接从起点开始走,但是每次到达一个新结点时要保证d值恰好减少1(如有个选择则可以随便走),直到到达终点。
直接从起点开始按照上述规则走,如果有多种走法,选颜色字典序最小的走;如果有多条边的颜色字典序都是最小,则记录所有这些边的终点,走下一步时要考虑从所有这些点出发的边。这实际上是又做了一次BFS,因此时间复杂度仍为O(m)。
#include <iostream> #include <cstdio> #include <vector> #include <cstring> #include <queue> using namespace std; typedef long long ll; const ll inf = 1e9 + 5; const int maxn = 100000 + 5; int n, m, d[maxn], vis[maxn], nextNode[maxn], tempNode[maxn]; struct edge { int v, w; edge(int b, int c) : v(b), w(c) {} }; vector<edge> e[maxn]; int main(void) { while (~scanf("%d %d", &n, &m)) { memset(vis, 0, sizeof(vis)); memset(d, inf, sizeof(d)); for (int i = 1; i <= n; i++) e[i].clear(); while (m--) { int a, b; ll c; scanf("%d %d %lld", &a, &b, &c); e[a].push_back(edge(b, c)); e[b].push_back(edge(a, c)); } queue<int> Q; Q.push(n); vis[n] = 1; d[n] = 0; while (!Q.empty()) { int u = Q.front(); Q.pop(); for (int i = 0; i < e[u].size(); i++) { int v = e[u][i].v; if (vis[v]) continue; vis[v] = 1; d[v] = d[u] + 1; Q.push(v); } } memset(vis, 0, sizeof(vis)); vis[1] = 1; int size = 0; nextNode[size++] = 1; printf("%d\n", d[1]); for (int step = 0; step < d[1]; step++) { int cnt = 0; ll minColor = inf; for (int i = 0; i < size; i++) { int u = nextNode[i]; //所有的u和n的距离都相同 for (int j = 0; j < e[u].size(); j++) { int v = e[u][j].v; if (d[v] != d[u] - 1) continue; //保证再走一步会缩小距离 if (e[u][j].w <= minColor) { //找最小的颜色 if (e[u][j].w < minColor) { cnt = 0; minColor = e[u][j].w; } tempNode[cnt++] = v; } } } printf("%lld%c", minColor, (step == d[1] - 1) ? '\n' : ' '); int cnt2 = 0; for (int i = 0; i < cnt; i++) { if (vis[tempNode[i]]) continue; vis[tempNode[i]] = 1; nextNode[cnt2++] = tempNode[i]; } size = cnt2; } } system("pause"); return 0; }
转载请注明出处:https://www.cnblogs.com/stu-jyj3621

浙公网安备 33010602011771号