题意
求带边权无向图从起点到终点的边权字典序最小的最短路路径
解法
两遍 BFS
第一遍逆向,给图分层
第二遍求路径,每层的点都只能沿最小的边权走向下一层的点。
代码
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <queue> using namespace std; typedef long long LL; const int inf=0x3f3f3f3f; const LL INF=0x3f3f3f3f3f3f3f3f; const int MAXN=1e5+10; int n,m; int head[MAXN],nxt[MAXN*4],to[MAXN*4],c[MAXN*4],tot=1; int dis[MAXN],from[MAXN],path[MAXN]; bool vis[MAXN]; queue<int> que; queue<vector<int> > q2; void add(int u,int v,int w){ to[++tot]=v;c[tot]=w;nxt[tot]=head[u];head[u]=tot; to[++tot]=u;c[tot]=w;nxt[tot]=head[v];head[v]=tot; } void bfs1(){ while(!que.empty()) que.pop(); memset(dis,0x3f,sizeof(dis)); dis[n]=0;que.push(n); while(!que.empty()){ int u=que.front();que.pop(); for(int i=head[u];i;i=nxt[i]) if(dis[to[i]]>dis[u]+1){ dis[to[i]]=dis[u]+1; que.push(to[i]); } } } void bfs2(){ memset(path,0x3f,sizeof(path)); memset(vis,0,sizeof(vis)); vector<int> vec; vec.push_back(1); q2.push(vec); while(!q2.empty()){ vector<int> uv=q2.front();q2.pop(); vec.clear(); int color=inf; for(int i=0;i<uv.size();i++){ int u=uv[i]; for(int j=head[u];j;j=nxt[j]) if(dis[to[j]]==dis[u]-1) color=min(color,c[j]); } for(int i=0;i<uv.size();i++){ int u=uv[i]; for(int j=head[u];j;j=nxt[j]) if(dis[to[j]]==dis[u]-1&&c[j]==color&&!vis[to[j]]){ from[to[j]]=u; path[to[j]]=color; vec.push_back(to[j]); vis[to[j]]=1; } } if(!vec.empty()) q2.push(vec); } } void print(int now){ if(now==1) return; print(from[now]); printf("%d",path[now]); if(now!=n) printf(" "); } void solve(){ tot=1; memset(head,0,sizeof(head)); for(int i=1,u,v,w;i<=m;i++){ scanf("%d%d%d",&u,&v,&w); add(u,v,w); } bfs1(); bfs2(); printf("%d\n",dis[1]); print(n); printf("\n"); } int main(){ while(~scanf("%d%d",&n,&m)) solve(); return 0; }