思路:两趟BFS。
第一趟从终点开始BFS,到达起点后停止。目的是求得从起点到终点道路(可能不止一条)上的点到终点的最短距离,将这些点按照距离远近分层,用一个数组记录。
第二趟从起点开始正向做一次BFS,每次都选取颜色最小的路径,同时要保证距离的值刚好减1,如果有多条路可以走,则要记录这些结点,下一步需要考虑所有从这些点出发的边。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <climits>
#include <algorithm>
using namespace std;
const int N = 100010;
vector<int> G[N]; // 边
vector<int> Color[N]; // 颜色
int step[N];
int ans[N*2];
bool vis[N];
void reverse_bfs( int n ) {
memset( step,-1,sizeof(step) );
step[n] = 0; //终点离终点距离为0
queue<int> Q;
Q.push( n );
while( !Q.empty() ) {
int u = Q.front(); Q.pop();
int ver_num = G[u].size(); //点u相连的边数
for( int i=0; i<ver_num; ++i ) {
int p = G[u][i]; //u相连的点
//是源点,则结束
if( p==1 ) {
step[1] = step[u] + 1; return;
}
//判重。如果没有入过队才能入队
if( step[p]==-1) {
step[p] = step[u] + 1;
Q.push( p );
}
}
}
}
void bfs() {
memset( ans,0,sizeof(ans) );
memset( vis,false,sizeof(vis) );
queue<int> Q;
Q.push( 1 ); vis[1] = true;
while( !Q.empty() ) {
int u = Q.front(); Q.pop();
if( step[u]==0 ) return; //到达终点
int ver_num = G[u].size(); //边数
int min_color = -1; // 最小的颜色
//找最小颜色的边
for( int i=0; i<ver_num; ++i ) {
int v = G[u][i];
if( step[v]==step[u]-1 ) {
if( min_color==-1 ) min_color = Color[u][i];
else min_color = min( min_color, Color[u][i] );
}
}
int idx = step[1]-step[u];
if( ans[idx]==0 ) ans[idx] = min_color;
//cout<<"idx "<<idx<<" mincolor : "<<min_color<<endl;
else ans[idx] = min( ans[idx],min_color );
//cout<<"ans0 : "<<ans[0]<<endl;
//找到所有颜色最小的边的点,入队
for( int i=0; i<ver_num; ++i ) {
int v = G[u][i];
if( !vis[v]&&step[v]==step[u]-1&&Color[u][i]==min_color ) {
Q.push( v );
vis[v] = true;
}
}
}
}
int main()
{
int n,m;
int a,b,c;
while( cin>>n>>m ) {
for( int i=0; i<N; ++i ) {
G[i].clear();
Color[i].clear();
}
for( int i=0; i<m; ++i ) {
cin>>a>>b>>c;
G[a].push_back( b );
G[b].push_back( a );
Color[a].push_back( c );
Color[b].push_back( c );
}
//cout<<"finish input"<<endl;
reverse_bfs( n );
//cout<<"reverse bs"<<endl;
bfs();
cout<<step[1]<<endl;
for( int i=0; i<step[1]; ++i ) {
if( i>=1 ) cout<<" "<<ans[i];
else cout<<ans[i];
}cout<<endl;
}
return 0;
}