New labyrinth attraction is open in New Lostland amusement park. The labyrinth consists of n rooms connected by m passages. Each passage is colored into some color ci. Visitors of the labyrinth are dropped from the helicopter to the room number 1 and their goal is to get to the labyrinth exit located in the room number n.
Labyrinth owners are planning to run a contest tomorrow. Several runners will be dropped to the room number 1. They will run to the room number n writing down colors of passages as they run through them. The contestant with the shortest sequence of colors is the winner of the contest. If there are several contestants with the same sequence length, the one with the ideal path is the winner. The path is the ideal path if its color sequence is the lexicographically smallest among shortest paths.
Andrew is preparing for the contest. He took a helicopter tour above New Lostland and made a picture of the labyrinth. Your task is to help him find the ideal path from the room number 1 to the room number nthat would allow him to win the contest.
Note
A sequence ( a1, a2, . . . , ak) is lexicographically smaller than a sequence ( b1, b2, . . . , bk) if there exists i such that ai < bi, and aj = bj for all j < i.
Input
The first line of the input file contains integers n and m —the number of rooms and passages, respectively (2 <= n <= 100 000, 1 <= m <= 200 000). The following m lines describe passages, each passage is described with three integer numbers: ai, bi, and ci — the numbers of rooms it connects and its color (1 <= ai, bi <= n, 1 <= ci <= 10 9). Each passage can be passed in either direction. Two rooms can be connected with more than one passage, there can be a passage from a room to itself. It is guaranteed that it is possible to reach the room number n from the room number 1.
Output
The first line of the output file must contain k — the length of the shortest path from the room number 1 to the room number n. The second line must contain k numbers — the colors of passages in the order they must be passed in the ideal path.
Sample Input
4 6 1 2 1 1 3 2 3 4 3 2 3 1 2 4 4 3 1 1
Sample Output
2 1 3
解题思路:
两次BFS,这题还真有点难
首先反向BFS,求得每个点距离终点的最短距离
然后从起点1开始正向BFS,寻找最短的字典序距离,遍历每个结点的邻接结点,如果满足d[当前结点]-1=d[邻接结点],就把它们之间的边权与最小边权比较并保存
如果遇到最小边权有多条的情况,就把这些邻接结点都加入BFS队列
注意:题目输入会出现自环的情况,这种情况要排除
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <vector>
#include <queue>
using namespace std;
const int INF = 0x3fffffff;
const int MAXN = 200010;
int N, M;
struct sedge {
int to, col;
};
vector<sedge> sEdges[MAXN];
bool svisit[MAXN];
bool isInQueue[MAXN];
int sdis[MAXN];
int qres[MAXN];
//正向BFS
void bfs(int starts, int ends) {
queue<int> bfs_node;
vector<int> vs;
memset(isInQueue, false, sizeof(isInQueue));
memset(svisit, false, sizeof(svisit));
fill(qres, qres + MAXN, 0); //赋值为0
bfs_node.push(starts);
while (!bfs_node.empty()) {
int u = bfs_node.front();
bfs_node.pop();
int minC = INF;
svisit[u] = true;
//将当前结点所指向的结点的最小值保留
for (int i = 0; i < sEdges[u].size(); ++i) {
if (!svisit[sEdges[u][i].to] && sdis[u] - 1 == sdis[sEdges[u][i].to]) {
if (sEdges[u][i].col < minC) {
minC = sEdges[u][i].col; //将最小值保留
vs.clear();
vs.push_back(sEdges[u][i].to);
}
else{
if (sEdges[u][i].col == minC) {
vs.push_back(sEdges[u][i].to); //直接加入vs
}
}
}
}
//将重复的的元素放入到队列中
for (int i = 0; i < vs.size(); ++i) {
if (!isInQueue[vs[i]]) {
isInQueue[vs[i]] = true;
bfs_node.push(vs[i]);
}
}
//然后更新结果
int snIndex = sdis[0] - sdis[u];
if (qres[snIndex] == 0) {
qres[snIndex] = minC;
}
else {
qres[snIndex] = min(qres[snIndex], minC);
}
}
}
//反向BFS
void rbfs(int starts, int ends) {
memset(svisit, false, sizeof(svisit));
memset(isInQueue, false, sizeof(isInQueue));
queue<int> bfs_node;
bfs_node.push(starts);
sdis[N-1] = 0;
while (!bfs_node.empty()) {
int u = bfs_node.front();
bfs_node.pop();
svisit[u] = true;
for (int i = 0; i < sEdges[u].size(); ++i) {
if (!svisit[sEdges[u][i].to] && !isInQueue[sEdges[u][i].to]) {
sdis[sEdges[u][i].to] = sdis[u] + 1; //依次累加得到距离终点的距离
isInQueue[sEdges[u][i].to] = true;
bfs_node.push(sEdges[u][i].to);
}
}
}
}
int main() {
while (scanf("%d %d", &N, &M) != EOF) {
for (int i = 0; i < N; ++i) {
sEdges[i].clear(); //清空
}
memset(sdis, -1, sizeof(sdis));
int tx, ty, tcol;
for (int i = 0; i < M; ++i) {
scanf("%d %d %d", &tx, &ty, &tcol);
if (tx != ty) { //自环!!
sedge a;
tx = tx - 1;
ty = ty - 1;
a.to = ty, a.col = tcol;
sEdges[tx].push_back(a);
a.to = tx;
sEdges[ty].push_back(a);
}
}
rbfs(N-1, 0);
bfs(0, N-1);
printf("%d\n", sdis[0]);
printf("%d", qres[0]);
for (int i = 1; i < sdis[0]; ++i) {
printf(" %d", qres[i]);
}
printf("\n");
}
system("PAUSE");
return 0;
}