给一个n个点m条边(<=n<=,<=m<=)的无向图,每条边上都涂有一种颜色。求从结点1到结点n的一条路径,使得经过的边数尽量少,在此前提下,经过边的颜色序列的字典序最小。一对结点间可能有多条边,一条边可能连接两个相同结点。输入保证结点1可以达到结点n。颜色为1~^9的整数。
第一次bfs逆向搜索,得到每个点到终点的最短距离,找出最短路;第二次bfs根据最短距离可以选择满足条件的最短路。
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<bitset>
#include<map>
#include<vector>
#include<stdlib.h>
#include <stack>
using namespace std;
int dirx[]={,,-,};
int diry[]={-,,,};
#define PI acos(-1.0)
#define max(a,b) (a) > (b) ? (a) : (b)
#define min(a,b) (a) < (b) ? (a) : (b)
#define ll long long
#define eps 1e-10
#define MOD 1000000007
#define N 100006
#define inf 1e12
int n,m;
vector<int>G[N];
vector<int>C[N];
int dis[N];
int vis[N];
int ans[N];
void bfs1(){//得到每一点到终点的最短距离的模板
queue<int> q;
q.push(n);
dis[n]=;
while(!q.empty()){
int u=q.front();
q.pop(); for(int i=;i<G[u].size();i++){
int v=G[u][i];
if(v==){
dis[v]=dis[u]+;
return;
}
if(dis[v]==-){
dis[v]=dis[u]+;
q.push(v);
}
}
}
}
void bfs2(){
queue<int> q;
q.push();
while(!q.empty()){
int u=q.front();
q.pop();
if(dis[u]==){
return;
}
int minn=-;
for(int i=;i<G[u].size();i++){
int v=G[u][i];
if(dis[v]==dis[u]-){
if(minn==-){
minn=C[u][i];
}
else{
minn=min(minn,C[u][i]);
}
}
} int t=dis[]-dis[u];
if(ans[t]==){
ans[t]=minn;
}
else{
ans[t]=min(ans[t],minn);
} for(int i=;i<G[u].size();i++){
int v=G[u][i]; if(vis[v]== && dis[v]==dis[u]- && C[u][i]==minn){
q.push(v);
vis[v]=;
}
}
}
}
int main()
{
while(scanf("%d%d",&n,&m)==){
for(int i=;i<N;i++){
G[i].clear();
C[i].clear();
dis[i]=-;
vis[i]=;
ans[i]=;
}
for(int i=;i<m;i++){
int x,y,c;
scanf("%d%d%d",&x,&y,&c);
G[x].push_back(y);
G[y].push_back(x);
C[x].push_back(c);//存 颜 色
C[y].push_back(c);
}
bfs1();//求 出 每 一 点 到 n 的 最 短 距 离
printf("%d\n",dis[]);
bfs2();//从 1开始找最短的路径 ,以及字典序最小
for(int i=;i<dis[];i++){
if(i){
printf(" ");
}
printf("%d",ans[i]);
}
printf("\n");
}
return ;
}