这题就是裸的最短路,而且边权都为非负,可以直接用dijkstra来求。
写这题主要是为了练习一下dijkstra的优先级队列实现,提交后运行时间为63MS,比一般的dijkstra快一点(97MS)。
后来又尝试用SPFA写,结果还是63MS。
在写dijkstra的优先级队列实现和SPFA的过程中发现,这两个算法非常类似,不过,SPFA用的是一般的队列。
SPFA
#include <stdio.h> #include <string.h> #include <queue> using namespace std; #define MIN(a,b) ((a)<(b)?(a):(b)) #define N 1000 #define INF 100000 int n,m; int d[N][N],dist[N],inq[N]; struct node { int u; friend bool operator <(node x,node y) { return dist[x.u]>dist[y.u]; } }; void spfa(int s) { int u,v; node cur,next; queue<node> q; memset(inq,0,sizeof(inq)); for(u=0;u<n;u++) dist[u]=INF; dist[s]=0; cur.u=s; q.push(cur); inq[s]=1; while(!q.empty()) { cur=q.front(),q.pop(); u=cur.u; inq[u]=0; for(v=0;v<n;v++) { if(dist[v]>dist[u]+d[u][v]) { dist[v]=dist[u]+d[u][v]; next.u=v; if(inq[v]==0) q.push(next); } } } } int main() { int i,j,a,b,x; while(~scanf("%d%d",&m,&n)) { for(i=0;i<n;i++) { for(j=0;j<i;j++) d[i][j]=d[j][i]=INF; } for(i=0;i<m;i++) { scanf("%d%d%d",&a,&b,&x); a--,b--; d[a][b]=d[b][a]=MIN(d[a][b],x); } spfa(0); printf("%d\n",dist[n-1]); } return 0; }
优先级队列实现的dijkstra
#include <stdio.h> #include <string.h> #include <queue> #define MIN(a,b) ((a)<(b)?(a):(b)) #define N 1000 #define INF 100000 using namespace std; int n,m; int d[N][N]; int dist[N],vis[N]; struct node { int u,g; friend bool operator <(node x,node y) { return x.g>y.g; } }; void dijkstra(int s) { int u,v,gu,gv; node cur,next; priority_queue<node> pq; memset(vis,0,sizeof(vis)); for(u=0;u<n;u++) dist[u]=INF; cur.u=s; cur.g=0; pq.push(cur); while(!pq.empty()) { cur=pq.top(),pq.pop(); u=cur.u; gu=cur.g; vis[u]++; if(vis[u]>1) continue; dist[u]=gu; for(v=0;v<n;v++) { if(vis[v]==0 && dist[v]>=gu+d[u][v]) { dist[v]=gv=gu+d[u][v]; next.u=v; next.g=gv; pq.push(next); } } } } int main() { int i,j,a,b,x; while(~scanf("%d%d",&m,&n)) { for(i=0;i<n;i++) { for(j=0;j<i;j++) d[i][j]=d[j][i]=INF; } for(i=0;i<m;i++) { scanf("%d%d%d",&a,&b,&x); a--,b--; d[a][b]=d[b][a]=MIN(d[a][b],x); } dijkstra(0); printf("%d\n",dist[n-1]); } return 0; }