给一个n个点m条边(2<=n<=100000,1<=m<=200000)的无向图,每条边上都涂有一种颜色。求从结点1到结点n的一条路径,使得经过的边数尽量少,在此前提下,经过边的颜色序列的字典序最小。一对结点间可能有多条边,一条边可能连接两个相同结点。输入保证结点1可以达到结点n。颜色为1~10^9的整数。
第一次bfs逆向搜索,得到每个点到终点的最短距离,找出最短路;第二次bfs根据最短距离可以选择满足条件的最短路。
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<math.h> 7 #include<algorithm> 8 #include<queue> 9 #include<set> 10 #include<bitset> 11 #include<map> 12 #include<vector> 13 #include<stdlib.h> 14 #include <stack> 15 using namespace std; 16 int dirx[]={0,0,-1,1}; 17 int diry[]={-1,1,0,0}; 18 #define PI acos(-1.0) 19 #define max(a,b) (a) > (b) ? (a) : (b) 20 #define min(a,b) (a) < (b) ? (a) : (b) 21 #define ll long long 22 #define eps 1e-10 23 #define MOD 1000000007 24 #define N 100006 25 #define inf 1e12 26 int n,m; 27 vector<int>G[N]; 28 vector<int>C[N]; 29 int dis[N]; 30 int vis[N]; 31 int ans[N]; 32 void bfs1(){//得到每一点到终点的最短距离的模板 33 queue<int> q; 34 q.push(n); 35 dis[n]=0; 36 while(!q.empty()){ 37 int u=q.front(); 38 q.pop(); 39 40 for(int i=0;i<G[u].size();i++){ 41 int v=G[u][i]; 42 if(v==1){ 43 dis[v]=dis[u]+1; 44 return; 45 } 46 if(dis[v]==-1){ 47 dis[v]=dis[u]+1; 48 q.push(v); 49 } 50 } 51 } 52 } 53 void bfs2(){ 54 queue<int> q; 55 q.push(1); 56 while(!q.empty()){ 57 int u=q.front(); 58 q.pop(); 59 if(dis[u]==0){ 60 return; 61 } 62 int minn=-1; 63 for(int i=0;i<G[u].size();i++){ 64 int v=G[u][i]; 65 if(dis[v]==dis[u]-1){ 66 if(minn==-1){ 67 minn=C[u][i]; 68 } 69 else{ 70 minn=min(minn,C[u][i]); 71 } 72 } 73 } 74 75 int t=dis[1]-dis[u]; 76 if(ans[t]==0){ 77 ans[t]=minn; 78 } 79 else{ 80 ans[t]=min(ans[t],minn); 81 } 82 83 for(int i=0;i<G[u].size();i++){ 84 int v=G[u][i]; 85 86 if(vis[v]==0 && dis[v]==dis[u]-1 && C[u][i]==minn){ 87 q.push(v); 88 vis[v]=1; 89 } 90 } 91 } 92 } 93 int main() 94 { 95 while(scanf("%d%d",&n,&m)==2){ 96 for(int i=0;i<N;i++){ 97 G[i].clear(); 98 C[i].clear(); 99 dis[i]=-1; 100 vis[i]=0; 101 ans[i]=0; 102 } 103 for(int i=0;i<m;i++){ 104 int x,y,c; 105 scanf("%d%d%d",&x,&y,&c); 106 G[x].push_back(y); 107 G[y].push_back(x); 108 C[x].push_back(c);//存 颜 色 109 C[y].push_back(c); 110 } 111 bfs1();//求 出 每 一 点 到 n 的 最 短 距 离 112 printf("%d ",dis[1]); 113 bfs2();//从 1开始找最短的路径 ,以及字典序最小 114 for(int i=0;i<dis[1];i++){ 115 if(i){ 116 printf(" "); 117 } 118 printf("%d",ans[i]); 119 } 120 printf(" "); 121 } 122 return 0; 123 }