点击打开题目链接
给一个n个点m条边的无向图,每个边标记一种颜色(1~1e9),求一条从1到n的路径,使得经过边尽量少的前提下颜色序列字典序最小。
思路:
1.忽略自环的边,用邻接表建图
2.逆序bfs求出每个顶点到n的最短距离。
3.顺序bfs从顶点1开始按照每次到n最短距离-1来寻找剩余顶点,多个顶点满足时按照最小颜色走,颜色相同时进队列,最小颜色记在ans[]中。
*vis[]保证顶点不重复进队列,不然会T掉。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100000 + 5;
const int INF = 1e9 + 5;
int dis[maxn];
int n, m;
int ans[maxn];
int vis[maxn];
typedef pair<int, int> p; //first len second id
struct edge {
int to, color;
};
vector<edge> g[maxn];
int read_input() {
//init
for(int i = 0; i <= n; i++) {
g[i].clear();
vis[i] = 0;
dis[i] = ans[i] = INF;
}
//input
for(int i = 0; i < m; i++) {
edge e;
int from;
cin >> from >> e.to >> e.color;
if(from == e.to) continue;
g[from].push_back(e);
swap(from, e.to);
g[from].push_back(e);
}
return 1;
}
void anti_bfs() {
queue<int> que;
que.push(n);
dis[n] = 0;
while(!que.empty()) {
int v = que.front(); que.pop();
for(int i = 0; i < g[v].size(); i++) {
edge e = g[v][i];
if(dis[e.to] == INF) {
dis[e.to] = dis[v] + 1;
que.push(e.to);
}
}
}
return;
}
void bfs() {
queue<int> que;
que.push(1);
while(!que.empty()) {
int d = INF;
int u = que.front(); que.pop();
for(int i = 0; i < g[u].size(); i++) {
edge e = g[u][i];
if(dis[e.to] == dis[u] - 1 && e.color < d) {
d = e.color;
}
}
int cur = dis[1] - dis[u];
if(ans[cur] > d) ans[cur] = d;
for(int i = 0; i < g[u].size(); i++) {
edge e = g[u][i];
if(vis[e.to] == 0 && dis[e.to] == dis[u] - 1 && e.color == d) {
que.push(e.to);
vis[e.to] = 1;
}
}
}
return;
}
int main() {
ios::sync_with_stdio(false);
while(cin >> n >> m) {
read_input();
anti_bfs();
bfs();
cout << dis[1] << endl;
for(int i = 0; i < dis[1]; i++) {
if(i == 0) cout << ans[i];
else cout << ' ' << ans[i];
}
cout << endl;
}
}