思路 :紫书上的思路,先从终点反向BFS找出每一个点到终点的最短距离,然后正向BFS 一个循环内套两个循环,第一个循环找出最小的颜色,第二个循环把符合条件的点放入类似队列的数组(vector)然后一直搜 就能找出来了
#include<bits/stdc++.h>
using namespace std;
const int maxn=100000+10;
struct Edge{
int u,v,c;
Edge(int a=0,int b=0,int c=0):u(a),v(b),c(c){}
};
vector<Edge>edges; //用邻接表存图
vector <int>G[maxn];
void Add_edges(int u,int v,int c){
edges.push_back(Edge(u,v,c));
int index=edges.size()-1;
G[u].push_back(index);
}
int vis[maxn];
int d[maxn];
int n;
void rev_bfs(){
memset(vis,0,sizeof(vis)); //第一次BFS 找出每个点到终点的最小距离
d[n-1]=0;
queue<int>q;
q.push(n-1);
vis[n-1]=1;
while(!q.empty()){
int temp=q.front();
q.pop();
for(int i=0;i<G[temp].size();i++){
int e=G[temp][i];
int u=edges[e].v;
if(!vis[u]){
vis[u]=1;
d[u]=d[temp]+1;
q.push(u);
}
}
}
}
vector<int>ans;
void bfs(){ //第二次BFS
memset(vis,0,sizeof(vis));
vis[0]=1;
ans.clear();
vector<int>next;
next.push_back(0);
for(int i=0;i<d[0];i++){ //一共d[0]步,所以循环d[0]次
int min_color=INT_MAX;
for(int j=0;j<next.size();j++){ //找出最小的颜色 其中next会在下面的循环更新
int u=next[j];
for(int k=0;k<G[u].size();k++){
int e=G[u][k];
int v=edges[e].v;
if(d[u]==d[v]+1){
min_color=min(min_color,edges[e].c);
}
}
}
ans.push_back(min_color); //把最小的颜色存起来
vector<int>next2;
for(int j=0;j<next.size();j++){
int u=next[j];
for(int k=0;k<G[u].size();k++){
int e=G[u][k];
int v=edges[e].v;
if(d[u]==d[v]+1&&edges[e].c==min_color&&!vis[v]){
vis[v]=1;
next2.push_back(v); //把符合条件的点存起来
}
}
}
next=next2;//把符合最小颜色的点的数组更新上一个next数组实现bfs
}
printf("%d\n",ans.size());
printf("%d",ans[0]);
for(int i=1;i<ans.size();i++){
printf(" %d",ans[i]);
}
printf("\n");
}
int main(){
int u,v,c,m;
while(scanf("%d%d",&n,&m)==2){
for(int i=0;i<n;i++)G[i].clear();
while(m--){
scanf("%d%d%d",&u,&v,&c);
Add_edges(u-1,v-1,c);
Add_edges(v-1,u-1,c);
}
rev_bfs();
bfs();
}
return 0;
}