UVa1599
房间和房间之间存在路径,路径的颜色用整数表示,找到一个从编号为1
的房间到编号为n
的房间的一条理想路径。理想路径是字典序最小的路径。
- 虽然房间数量多达
100000
,但我还是试了一下朴素的深搜,超时了 - 然后我又试了朴素的广搜,并在广搜过程中记录了从房间
1
到各个房间的理想路径,还是超时了。相对于穷举全部理想路径的深搜,广搜只需要穷举全部最短的理想路径 - 为了省事,上面两种方法都是用的邻接矩阵存储的图,所以我又把广搜中的邻接矩阵换成邻接表试了一下(为了去掉重复的路径,其实邻接的是
map
),还是超时了,但此时uDebug上超长的测试用例已经可以在很短的时间内跑出来了,这是因为广搜每一次扩展时访问的节点数量已经少很多很多了 - 广搜已经是最优了,还能优化的就是只求解房间
1
到房间n
的理想路径,所以我又改成了从编号为n
的房间反向广搜来统计各个房间到房间n
的最短路径长度,然后通过一次从房间1
开始的正向的迭代来求理想路径——以上就是网上各种两次BFS题解的分析思路 - 最后收获了一个PE,因为输出路径时最后一个颜色值后面多加了空格。
#include <iostream>
#include <algorithm>
#include <climits>
#include <deque>
#include <map>
#include <set>
#include <vector>
using namespace std;
class Solution
{
public:
Solution(const vector<map<size_t, size_t>> &rooms)
: graph(rooms), levels(rooms.size(), UINT_MAX), visited(rooms.size(), false)
{
SearchIdealPath();
}
void print(ostream &os)
{
os << IdealPath.size() << endl;
cout << IdealPath.front();
for(size_t i = 1; i < IdealPath.size(); i++)
{
cout << ' ' << IdealPath[i];
}
cout << endl;
}
private:
const vector<map<size_t, size_t>> &graph;
vector<size_t> levels, IdealPath;
vector<bool> visited;
void SearchIdealPath()
{
deque<size_t> q;
visited.back() = true;
q.push_back(graph.size() - 1);
levels.back() = 0;
while (!q.empty()) {
size_t curr = q.front();
q.pop_front();
if (curr == 0) break;
for (auto iter = graph[curr].begin(); iter != graph[curr].end(); iter++)
{
if (!visited[iter->first]) {
visited[iter->first] = true;
q.push_back(iter->first);
levels[iter->first] = levels[curr] + 1;
}
}
}
set<size_t> SameColor{ 0 };
while (1) {
size_t MinColor = UINT_MAX;
set<size_t> NextSameColor;
for (size_t curr : SameColor)
{
for (auto iter = graph[curr].begin(); iter != graph[curr].end(); iter++)
{
if (levels[iter->first] == levels[curr] - 1) {
if (iter->second < MinColor) {
NextSameColor.clear();
NextSameColor.insert(iter->first);
MinColor = iter->second;
}
else if (iter->second == MinColor) {
NextSameColor.insert(iter->first);
}
}
}
}
IdealPath.push_back(MinColor);
if (IdealPath.size() == levels.front()) break;
SameColor = NextSameColor;
}
}
};
int main()
{
size_t n, m;
while (cin >> n) {
cin >> m;
vector<map<size_t, size_t>> rooms(n);
for (size_t i = 0; i < m; i++)
{
size_t a, b, c;
cin >> a >> b >> c;
if (a == b) continue;
auto iter = rooms[a - 1].find(b - 1);
if (iter == rooms[a - 1].end()) {
rooms[a - 1][b - 1] = c;
rooms[b - 1][a - 1] = c;
}
else if(c < iter->second){
iter->second = c;
rooms[b - 1][a - 1] = c;
}
}
Solution solution(rooms);
solution.print(cout);
}
return 0;
}
/*
4 6
1 2 1
1 3 2
3 4 3
2 3 1
2 4 4
3 1 1
*/