JZOJ 5279 香港记者

一句话题意:一个带点权边权的无向图,输出从1号点到n号点的最短路中字典序最小的一条路径

样例输入:

8 9
1 2 3 4 5 6 7 8
1 2 2
2 3 3
3 8 3
1 4 3
4 5 2
5 8 1
1 6 1
6 7 2
7 8 3

样例输出:

6
1 4 5 8

思路:

跑一边spfa(单源最快),更新条件改成(当前路径更短 or (当前路径和原路径相等 and 当前路径字典序更小)),直接开一个pre数组维护当前点的前继就好。

建议自己写队列,实现只要两分钟(因为代码短),而且不会被卡STL(实际上也没什么变态出题人会去卡一个queue),习惯第一。

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 #include<vector>
 7 #define ll long long
 8 using namespace std;
 9 struct edge{
10     int next,to,w;
11     edge(){
12         to=w=0;next=-1;
13     }
14 }a[400100];
15 int n,m,first[200100],bk[200100];
16 ll dis[200100];bool vis[200100];
17 ll pre[200100];
18 struct Queue{
19     int q[300100],head,tail;
20     Queue(int k){
21         head=100000;tail=100001;memset(q,0,sizeof(q));
22         q[head]=k;
23     }
24     void push(int k){
25         if(dis[k]>dis[q[head]]) q[tail++]=k;
26         else q[--head]=k;
27     }
28     void pop(){
29         q[head++]=0;
30     }
31     int top(){
32         return q[head];
33     }
34     bool empty(){
35         return (head==tail);
36     }
37 };
38 void spfa(){
39     Queue q(n);
40     vis[n]=1;dis[n]=0;pre[n]=n;
41     int u,v,w,i;
42     while(!q.empty()){
43         u=q.top();q.pop();vis[u]=0;
44         for(i=first[u];~i;i=a[i].next){
45             v=a[i].to;w=a[i].w;
46             if(dis[v]>dis[u]+w||(dis[v]==dis[u]+w&&bk[pre[v]]>=bk[u])){
47                 dis[v]=dis[u]+w;
48                 pre[v]=u;
49                 if(!vis[v]){
50                     vis[v]=1;q.push(v);
51                 }
52             }
53         }
54     }
55 }
56 int main(){
57     scanf("%d%d",&n,&m);
58     for(int i=1;i<=n;i++){
59         first[i]=-1;dis[i]=0x3f3f3f3f3f3f3f;
60         scanf("%d",&bk[i]);
61     }
62     int t1,t2,t3;
63     for(int i=1;i<=m;i++){
64         scanf("%d%d%d",&t1,&t2,&t3);
65         a[i].to=t1;a[i].next=first[t2];a[i].w=t3;first[t2]=i;
66     }
67     spfa();
68     printf("%lld
%d ",dis[1],bk[1]);
69     int i=1;
70     while(i!=n){
71         printf("%d ",bk[pre[i]]);i=pre[i];
72     }
73 }
原文地址:https://www.cnblogs.com/dedicatus545/p/7445564.html