先从终点宽搜,得到每个点到终点的距离,保证最短路。
再从起点宽搜,保证字典序最小。
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
#include <sstream>
#include <cmath>
#include <queue>
#include <set>
using namespace std;
const int MAXN = 100000;
const int MAXCOLOR = 1000000000;
struct Point
{
int pos;
int color;
Point(int p=0, int c=0) :pos(p), color(c) {}
};
vector<Point> G[MAXN+2];
Point last[MAXN+2];
int dis[MAXN+2];
int n, m;
void read_maze()
{
for (int u = 1; u <= n; u++)
G[u].clear();
int u, v, c;
for (int i = 1; i <= m; i++)
{
scanf("%d%d%d", &u, &v, &c);
if (u != v)
{
G[u].push_back(Point(v, c));
G[v].push_back(Point(u, c));
}
}
}
void init_dis()
{
memset(dis, -1, sizeof(dis));
queue<int> q;
q.push(n);
dis[n] = 0;
while (!q.empty())
{
int u = q.front();
q.pop();
int sz = G[u].size();
for (int i = 0; i < sz; i++)
{
int v = G[u][i].pos;
if (dis[v] == -1)
{
dis[v] = dis[u] + 1;
q.push(v);
}
}
}
}
void _bfs()
{
for (int i = 1; i <= n; i++)
last[i].color = MAXCOLOR+2;
queue<int> q;
q.push(1);
last[1] = Point(0, 0);
while (!q.empty())
{
int u = q.front();
q.pop();
if (u == n)
return;
int sz = G[u].size();
int min_color = MAXCOLOR + 2;
for (int i = 0; i < sz; i++)
if (dis[G[u][i].pos] == dis[u] - 1)
min_color = min(min_color, G[u][i].color);
for (int i = 0; i < sz; i++)
{
int v = G[u][i].pos;
if (dis[v] == dis[u] - 1 && G[u][i].color == min_color && last[v].color > min_color)
{
last[v] = Point(u, min_color);
q.push(v);
}
}
}
}
void print_ans()
{
vector<int> ans;
int u = n;
while (u != 1)
{
ans.push_back(last[u].color);
u = last[u].pos;
}
printf("%d\n", ans.size());
for (int i = ans.size() - 1; i >= 0; i--)
printf("%d%s", ans[i], (!i) ? "\n" : " ");
}
int main()
{
while (scanf("%d%d", &n, &m) == 2)
{
read_maze();
init_dis();
_bfs();
print_ans();
}
return 0;
}