spfa次短路

钱逸凡

2018-09-18 20:08:38

Solution

看到题解里好多dijkstra的,我就来一篇spfa的吧 好像有很多题解说spfa要跑两遍? 但是我只用了一遍就A了啊 ## 思路: dist数组开二维,分别装最小距离和次小距离。 先像往常一样打一个spfa,然后往里面塞一些if就好了。 更新最小距离的条件不用说了, ### 更新次小距离的条件有三种: 1.更新了最小距离,要把上次的最小距离先拿给次小距离(刚开始没想到这个条件,调了好久),因为上次的最小距离就是比当前距离大且最小的距离(即为次短距离)。 2.虽然可能当前路径无法更新最小距离,但可能更新次小距离,要加判断 3.从上一个点的次短距离更新这一个点的次短距离 ### 注意: 想转移次短距离,必须保证该距离小于最短距离。 ### 完整代码: ``` #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<queue> using namespace std; inline int Read(){ int x=0; char c=getchar(); while(c>'9'||c<'0')c=getchar(); while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar(); return x; } int n,m; int dist[10101][2];//dist[i][0]装最短路,dist[i][1]次短路 struct Node{ int v; int next; int val; }node[202020]; int head[5050],top; inline void addedge(int u,int v,int val){ node[++top].v=v; node[top].val=val; node[top].next=head[u]; head[u]=top; } inline void add(int u,int v,int val){ addedge(u,v,val); addedge(v,u,val); } int inque[5050]; void spfa(){ int s=1; memset(dist,0x3f,sizeof(dist)); queue<int>q; q.push(s); dist[s][0]=0; dist[s][1]=0; while(!q.empty()){ int u=q.front(); q.pop(); inque[u]=0; for(int i=head[u];i;i=node[i].next){ int d=node[i].v; if(dist[d][0]>dist[u][0]+node[i].val){ dist[d][1]=dist[d][0];//条件1 dist[d][0]=dist[u][0]+node[i].val; if(inque[d]==0){ q.push(d); inque[d]=1; } } if( (dist[d][1]>dist[u][0]+node[i].val&&dist[u][0]+node[i].val>dist[d][0]) ||(dist[d][1]==dist[d][0])){//从最短路转移(条件2) dist[d][1]=dist[u][0]+node[i].val; if(inque[d]==0){ q.push(d); inque[d]=1; } } if(dist[d][1]>dist[u][1]+node[i].val&&dist[u][1]+node[i].val>dist[d][0]){//从次短路转移(条件3) dist[d][1]=dist[u][1]+node[i].val; if(inque[d]==0){ q.push(d); inque[d]=1; } } } } } int main(){ register int i; int u,v,val; n=Read(),m=Read(); for(i=1;i<=m;i++){ u=Read(),v=Read(),val=Read(); add(u,v,val); } spfa(); printf("%d",dist[n][1]); return 0; } ```