最短路(floyd,dijkstra,spfa)

最短路

[floyd]
思考枚举 k 作为中转点来进行赋最小值,
原转移为 a[k][i][j]=min(a[k][i][j],a[k1][i][k1],a[k1][k1][j]);
经空间压缩后为 a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
注:为多源最短路
核心代码:

void floyd(){
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
}
}
}
}

[dijkstra]
一种基于贪心的算法,每次弹出堆中的点,
对所有与其相连的点进行松弛操作,
然后将松弛成功且还未以其作为松弛起点的点加入堆,
准备下一次松弛。
(松弛,即查看以当前节点为中转点的最短路是否比目标节点的最短路小,小即更新)
注:无法处理负权
核心代码:

typedef pair<int,int> P;
struct node{
int to,len;
};
//dis为最短路径,mp为临接表,vis为标记数组
void dijkstra(int s){
priority_queue<P,vector<P>,greater<P> >q;
dis[s]=0;
q.push(P{dis[s],s});
while(!q.empty()){
int l=q.top().second;
q.pop();
if(vis[l]){
continue;
}
vis[l]=1;
for(auto v:mp[l]) {
if(dis[v.to]>dis[l]+v.len){
dis[v.to]=dis[l]+v.len;
q.push(P{dis[v.to],v.to});
}
}
}
}

[spfa]
每次弹出队列中的点对周围进行松弛操作,
将松弛成功的点加入队列(不论是否其已经为松弛起点过),
一直执行到没有点可以松弛。
所以spfa可以处理负权环,当一个点被松弛了n次及以上说明该处有负权环。
但是你要是被卡了和floyd坐一桌
核心代码:

struct node{
int to,len;
};
//数组意思同上
void spfa(int s){
queue<int>q;
dis[s]=0;
vis[s]=1;
q.push(s);
while(!q.empty()){
int l=q.top();
q.pop();
vis[l]=0;
for(auto v:mp[l]){
if(dis[v.to]>dis[l]+v.len){
dis[v.to]=dis[l]+v.len;
if(!vis[l]){
q.push(v.to);
vis[l]=1;
}
}
}
}
}

1.accoders【一本通图 最短路径算法】 信使 2004
思路:
打一个dijkstra的板子,注意是无向图。
code:

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
struct node{
int to,len;
};
vector<node>mp[10010];
int dis[10010],vis[10010];
void dij(int s){
priority_queue<P,vector<P>,greater<P> >q;
dis[s]=0;
q.push(P{dis[s],s});
while(!q.empty()){
int l=q.top().second;
q.pop();
if(vis[l]){
continue;
}
vis[l]=1;
for(auto v:mp[l]){
if(dis[v.to]>dis[l]+v.len){
dis[v.to]=dis[l]+v.len;
q.push({dis[v.to],v.to});
}
}
}
}
int main(){
memset(dis,0x3f3f3f,sizeof dis);
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++){
int l,r,w;
cin>>l>>r>>w;
mp[l].push_back({r,w});
mp[r].push_back({l,w});
}
dij(1);
int ans=-1;
for(int i=1;i<=n;i++){
ans=max(ans,dis[i]);
}
if(ans>=0x3f3f00){
cout<<-1;
}else{
cout<<ans;
}
int _=0;
return (_^_^_);
}

2.accoders 【一本通提高篇SPFA算法的优化】Wormholes 虫洞2117
思路:
用spfa判断负环。
code:

#include<bits/stdc++.h>
using namespace std;
const int N=1000010,inf=0x3f3f3f3f;
int T;
int n,m,k;
int num[N],dis[N],vis[N];
struct node{
int to,len;
};
vector<node>e[N];
void init(){
memset(dis,inf,sizeof dis);
memset(num,0,sizeof num);
memset(vis,0,sizeof vis);
for(int i=1;i<=n;i++){
e[i].clear();
}
}
int spfa(int s){
queue<int>q;
dis[s]=0;
q.push(s);
vis[s]=1;
num[s]=1;
while(!q.empty()){
int u=q.front();
q.pop();
vis[u]=0;
for(auto v:e[u]){
if(dis[v.to]>dis[u]+v.len){
dis[v.to]=dis[u]+v.len;
if(!vis[v.to]){
num[v.to]++;
if(num[v.to]>n-1){
return 0;
}
q.push(v.to);
vis[v.to]=1;
}
}
}
}
return 1;
}
int main(){
cin>>T;
while(T--){
cin>>n>>m>>k;
init();
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
e[u].push_back({v,w});
e[v].push_back({u,w});
}
for(int i=1;i<=k;i++){
int u,v,w;
cin>>u>>v>>w;
e[u].push_back({v,-w});
}
if(spfa(1)){
cout<<"NO\n";
}else{
cout<<"YES\n";
}
}
return 0;
}

3.accoders【一本通图 最短路径算法】香甜的黄油2003
思路:
在每一个点跑一遍dijkstra,然后把到每个奶牛的距离加上,最后取min即可。
注:一个点可能有多个奶牛。

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
int dis[1010],sum[1010],vis[1010],fl[1010];
struct node{
int to,len;
};
vector<node> mp[1010];
void dijkstra(int s){
priority_queue<P,vector<P>,greater<P> >q;
dis[s]=0;
q.push(P{dis[s],s});
while(!q.empty()){
int l=q.top().second;
q.pop();
if(vis[l]){
continue;
}
vis[l]=1;
for(auto v:mp[l]){
if(dis[v.to]>dis[l]+v.len){
dis[v.to]=dis[l]+v.len;
q.push(P{dis[v.to],v.to});
}
}
}
}
int main(){
int n,p,c;
cin>>n>>p>>c;
for(int i=1;i<=n;i++){
int s;
cin>>s;
fl[s]++;
}
for(int i=1;i<=c;i++){
int l,r,w;
cin>>l>>r>>w;
mp[l].push_back({r,w});
mp[r].push_back({l,w});
}
for(int i=1;i<=p;i++){
memset(dis,0x3f3f3f3f,sizeof(dis));
memset(vis,0,sizeof(vis));
dijkstra(i);
for(int j=1;j<=p;j++){
sum[i]+=dis[j]*fl[j];
}
}
int mi=2e9;
for(int i=1;i<=p;i++){
mi=min(mi,sum[i]);
}
cout<<mi;
return 0;
}
posted @   lbh123  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!
< 2025年2月 >
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 1
2 3 4 5 6 7 8
点击右上角即可分享
微信分享提示