UVA-1599理想路径

思路:两趟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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值