Ideal Path UVA - 1599 (2次BFS)

本文介绍了一种解决迷宫竞赛问题的算法,通过两次BFS遍历找到从起点到终点的理想路径,即最短且字典序最小的颜色序列。首先进行反向BFS计算每个点到终点的最短距离,再正向BFS寻找理想路径,确保路径长度最短且颜色序列字典序最小。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 ( a1a2, . . . , ak) is lexicographically smaller than a sequence ( b1b2, . . . , 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: aibi, and ci — the numbers of rooms it connects and its color (1 <= aibi <= 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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值