先倒着BFS,找到每个结点i到重点最短距离d[i],然后直接起点开始BFS,如果有多种走法,选颜色字典序最小的走。
AC代码:
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; const int maxn = 100005; const int maxc = 1000000000; struct Edge { int u, v, c; Edge(int u = 0, int v = 0, int c = 0) : u(u), v(v), c(c) {} }; vector edges; vector G[maxn]; void addEdge(int u, int v, int c) { edges.push_back(Edge(u, v, c)); int idx = edges.size() - 1; G[u].push_back(idx); } int n, vis[maxn]; int d[maxn]; // 每个结点i到重点的最短距离d[i] // 从终点倒着BFS,找到到达n-1的最短路 void revBfs() { memset(vis, 0, sizeof(vis)); d[n - 1] = 0; vis[n - 1] = true; // 访问状态 queue q; q.push(n - 1); while (!q.empty()) { int v = q.front(); q.pop(); for (int i = 0; i < G[v].size(); i++) { int e = G[v][i]; int u = edges[e].v; if (!vis[u]) { // 还没有杯访问过 vis[u] = true; d[u] = d[v] + 1; q.push(u); } } } } vector ans; // 从起点开始BFS,如果有多种走法,选颜色字典序最小的走 void bfs() { memset(vis, 0, sizeof(vis)); vis[0] = true; ans.clear(); vector next; next.push_back(0); for (int i = 0; i < d[0]; i++) { int minColor = maxc; for (int j = 0; j < next.size(); j++) { int u = next[j]; for (int k = 0; k < G[u].size(); k++) { int e = G[u][k]; int v = edges[e].v; if (d[u] == d[v] + 1) { minColor = min(minColor, edges[e].c); } } } ans.push_back(minColor); // 再一次BFS vector next2; for (int j = 0; j < next.size(); j++) { int u = next[j]; for (int k = 0; k < G[u].size(); k++) { int e = G[u][k]; int v = edges[e].v; if (d[u] == d[v] + 1 && !vis[v] && edges[e].c == minColor) { vis[v] = true; next2.push_back(v); } } } next = next2; } printf("%d\n", ans.size()); printf("%d", ans[0]); for (int i = 1; i < ans.size(); i++) { printf(" %d", ans[i]); } printf("\n"); } int main() { int u, v, c, m; while (scanf("%d%d", &n, &m) == 2) { edges.size(); for (int i = 0; i < n; i++) { G[i].clear(); } while (m--) { scanf("%d%d%d", &u, &v, &c); addEdge(u - 1, v - 1, c); addEdge(v - 1, u - 1, c); } revBfs(); bfs(); } return 0; }
转载于:https://www.cnblogs.com/zhangyaoqi/p/4591547.html