最短路模板
阿新 • • 發佈:2022-05-17
1.dijkstra演算法:
從一點開始,更新所能到達的點的最小值,不能判斷有負權值的圖
模板:(與Prime演算法基本相同)
void dij(){//堆優化模板 priority_queue<pll,vector<pll>,greater<pll>> q; memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); q.push({0,1}); dis[1]=0; while(!q.empty()){ ll u=q.top().first;ll v=q.top().second; q.pop();if(vis[v]) continue; vis[v]=1; for(int i=head[v];i;i=e[i].next){ ll t=e[i].to; if(dis[t]>u+e[i].w){ dis[t]=u+e[i].w;q.push({dis[t],t}); } } } }
2.bellman-ford演算法:
就是一種遍歷,每條邊都要跑n次,最後再判斷能不能繼續鬆弛,能得話,說明有負權值邊。
模板:
ll bellman(){ memset(dis,0x3f,sizeof(dis)); dis[1]=0; for(int i=1;i<=n;i++){ for(int j=1;j<=cnt;j++){ if(dis[e[j].y]>dis[e[j].x]+e[j].w){ dis[e[j].y]=dis[e[j].x]+e[j].w; } } } for(int i=1;i<=cnt;i++){//繼續鬆弛,判斷有無負邊 if(dis[e[i].y]>dis[e[i].x]+e[i].w) return 1; } return 0; }
3 spfa演算法:
是bellman_ford的優化版本,bellman_ford演算法中,當某些點已經找到最短路時,就不需要再遍歷鬆弛,就可以省掉這一部分,保證每次都鬆弛沒有找到最短路的點。
判斷是否有負權值,有負權值,就可以無限鬆弛,正常情況下一個圖點數為n,它的鬆弛次數應為n-1,所以當 n(鬆弛次數)>=n-1時就證明有負權值
模板:
void spfa() memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[1]=0; queue<ll> q; q.push(1); vis[1]=1; while(!q.empty()){ ll t=q.front(); q.pop(); vis[t]=0; for(ll i=head[t];i;i=e[i].next){ ll j=e[i].to; if(dis[j]>dis[t]+e[i].w){ dis[j]=dis[t]+e[i].w; if(!vis[1]){ q.push(j);vis[j]=1; } } } } }
spfa判斷負環時:
ll spfa(){ memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); memset(num,0,sizeof(num)); dis[1]=0; queue<ll> q; for(ll i=1;i<=n;i++){ q.push(i);vis[i]=1; }//將所有點一次性存入和單獨將1存入都可以,前者快些 while(!q.empty()){ ll t=q.front(); q.pop(); vis[t]=0; for(ll i=head[t];i;i=e[i].next){ ll j=e[i].to; if(dis[j]>dis[t]+e[i].w){ num[j]=num[t]+1; if(num[j]>=n) return 1;//判斷鬆弛次數是否>=n dis[j]=dis[t]+e[i].w; if(!vis[j]){ q.push(j);vis[j]=1; } } } } return 0; }