UVA - 1599 Ideal Path (最小字典序最短路)
题意:无向图,边带权,问从1到n最少经过的结点数量,以及在此基础上经过的边权字典序最小的路径。
以1为源点bfs,每次把边权按从小到大的顺序进行遍历,边权相等的后继结点需要作为一个整体进行后续的bfs,这样能保证每个结点第一次被访问时的路径都是字典序最小的最短路径。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=1e5+10,inf=0x3f3f3f3f; 5 int hd[N],ne,d[N],fa[N],op[N],n,m; 6 struct E { 7 int u,v,c,nxt; 8 bool operator<(const E& b)const {return c<b.c;} 9 } e[N<<2]; 10 void link(int u,int v,int c) {e[ne]= {u,v,c,hd[u]},hd[u]=ne++;} 11 queue<int> q; 12 vector<E> vec; 13 void upd(int u,int c,int f,int o) {if(d[u]>c)d[u]=c,q.push(u),fa[u]=f,op[u]=o;} 14 void bfs() { 15 while(q.size())q.pop(); 16 memset(d,inf,sizeof d); 17 upd(1,0,0,0),q.push(-1); 18 while(q.size()) { 19 vec.clear(); 20 while(1) { 21 int u=q.front(); 22 q.pop(); 23 if(u==-1)break; 24 for(int i=hd[u]; ~i; i=e[i].nxt)vec.push_back(e[i]); 25 } 26 sort(vec.begin(),vec.end()); 27 for(int i=0,j,k; i<vec.size(); i=j) { 28 for(j=i+1; j<vec.size()&&vec[j].c==vec[i].c; ++j); 29 for(int k=i; k<j; ++k) { 30 int u=vec[k].u,v=vec[k].v,c=vec[k].c; 31 upd(v,d[u]+1,u,c); 32 } 33 q.push(-1); 34 } 35 } 36 } 37 int main() { 38 while(scanf("%d%d",&n,&m)==2) { 39 memset(hd,-1,sizeof hd),ne=0; 40 while(m--) { 41 int u,v,c; 42 scanf("%d%d%d",&u,&v,&c); 43 link(u,v,c); 44 link(v,u,c); 45 } 46 bfs(); 47 vector<int> ans; 48 for(int u=n; u!=1; u=fa[u])ans.push_back(op[u]); 49 reverse(ans.begin(),ans.end()); 50 printf("%d\n",ans.size()); 51 for(int i=0; i<ans.size(); ++i)printf("%d%c",ans[i]," \n"[i==ans.size()-1]); 52 } 53 return 0; 54 }