您的位置:首页 > 其它

最短路模板合集~(Dij+Floyd+Spfa)

2015-04-20 11:52 417 查看
自己整理的最短路模板,,对于最短路问题主要就是难在构图方面~~

//Dijstra   O(n^2)
//Dijkstra对于有负边权的最短路径不支持

void Dijstra()
{
int i,j;
for(i=0; i<n; ++i)
{
dis[i]=INF;
vis[i]=0;
}
dis[1]=0;
int v;
for(i=1; i<=n; ++i)
{
min=INF;
for(j=1; j<=n; ++j)
{
if(!vis[j]&&d[j]<min) //每次找点的过程,首先这个点没有被发现,然后找一个最小点
{
min=d[j];
v=j;
}
}
vis[v]=1;

for(j=1; j<=n; ++j) //加进最小点后,再修改从源点没有被发现的点的最短路径
{
if(!vis[j]&&dis[v]+mp[v][j]<dis[j])
dis[j]=dis[v]+mp[v][j];

}

}
int ans=-1;
for(i=1; i<=n; ++i)
if(dis[i]>ans)
ans=dis[i];

}

int main()
{

for(int i=0; i<n; ++i) //初始化 类似prim
for(int j=0; j<n; ++j)
{
if(i!=j)
mp[i][j]=INF;
else
mp[i][j]=0;
}

while(m--)
{
mp[i][j]=mp[j][i]=~~;
}

Dijstra();

return 0;

}

=============================================================

//Dijstra  优先队列+邻接表

//优化后复杂度为O(mlogn)

struct point
{
int val,id;
point(int id,int val):id(id),val(val) {}
bool operator <(const point &x)const
{
return val>x.val;
}
};
void dijkstra(int s)
{
memset(vis,0,sizeof(vis));
for(int i=0; i<n; i++)
dis[i]=INF;

priority_queue<point> q;
q.push(point(s,0));
vis[s]=true;
dis[s]=0;
while(!q.empty())
{
int cur=q.top().id;
q.pop();
vis[cur]=true;
for(int i=head[cur]; i!=-1; i=e[i].next)
{
int id=e[i].to;
if(!vis[id] && dis[cur]+e[i].val < dis[id])
{
dis[id]=dis[cur]+e[i].val;
q.push(point(id,dis[id]));
}
}
}
}

=============================================================

//Floyd    O(n^3)

void Floyd()
{
for(int i=0; i<n; ++i)
for(int j=0; j<n; ++j)
mp[i][j]=mp[j][i]=~~;

for(int i=0; i<n; ++i)
for(int j=0; j<n; ++j)
for(int k=0; k<n; ++k)
if(mp[j][k]>mp[j][i]+mp[i][k])
mp[j][k]=mp[j][i]+mp[i][k];

}

=============================================================

//Spfa 邻接矩阵   O(kE)E为边数,k一般为2或3
//可以计算带负环的回路

void Spfa()
{
int i,j;
for(int i=0; i<n; ++i)
{
d[i]=INF;
vis[i]=0;
}

queue<int>q;
q.push(start);
d[start]=0;
vis[start]=1;
while(!q.empty())
{
int v=q.front();
q.pop();
vis[v]=0;   // 这点别忘记

for(i=0; i<n; ++i)
{
if(d[i]>d[v]+mp[v][i])
{
d[i]=d[v]+mp[v][i];
if(!vis[i])
{
q.push(i);
vis[i]=1;

}

}

}

}
int ans=-1;
for(i=1; i<=n; ++i)
if(d[i]>ans)
ans=d[i];

}

int main()
{
for(int i=0; i<n; ++i)
for(int j=0; j<n; ++j)
{
if(i!=j)
mp[i][j]=INF;
else
mp[i][j]=0;
}

while(m--)
{
mp[i][j]=mp[j][i]=~~;
}

Spfa();

return 0;
}

=============================================================

//Spfa 邻接表(推荐)

struct node
{
int v;
int next;
int cost;
} Edge,e[M];

//Insert
//无向图的spfa的边要存两遍

void addEdge()
{
mp[cnt].v=to;
mp[cnt].cost=cost;
mp[cnt].next=headlist[from];
headlist[from]=cnt++;
mp[cnt].v=to;
mp[cnt].cost=cost;
mp[cnt].next=headlist[from];
headlist[from]=cnt++;

}

//

void Spfa()
{
int i,j;

for(i=0; i<n; ++i)
{
d[i]=INF;
vis[i]=0;

}

d[start]=0;
vis[start]=1;
queue<int>q;
q.push(start);
while(!q.empty())
{
int v==q.front();
q.pop();
vis[v]=0;
for(i=headlist[v]; i!=-1; i=mp[i].next)
{
int b=mp[i].v;
if(d[b]>d[v]+mp[i].cost)
{
d[b]=d[v]+mp[i].cost;
if(!vis[b])
{
vis[b]=1;
q.push(b);

}
}

}

}
int ans=-1;
for(i=1; i<n; ++i)
{
if(d[u]>ans)
ans=d[i];

}

}

int main()
{

//for(i=1; i<=n; i++)
//   headlist[i]=-1;
memset(head,-1,sizeof(head));

cnt=0;
cin>>from>>to>>cost;
// Insert(edge1,head1,u,v,w);
// Insert(edge2,head2,v,u,w);

}

=============================================================

Bellman_ford
// 这种算法比较少用,不多介绍了

//不断进行松弛操作
void bellman_ford()
{
int i,j,start=1;
for(i=1; i<=n; i++)
d[i]=INF;

d[start]=0;

for (i=1; i<n; i++)
{
//重复进行n-1次收缩
for (j=0; j<m; j++)
{
//对每条边进行收缩
if (d[t[j].u]+t[j].w<d[t[j].v])
d[t[j].v]=d[t[j].u]+t[j].w;
//分别对每条边的两个顶点分别进行收缩
if (d[t[j].v]+t[j].w<d[t[j].u])
d[t[j].u]=d[t[j].v]+t[j].w;
}
}       //简单说就是不断进行松弛
int ans=-1;
for(i=2; i<=n; i++)
if(d[i]>ans)
ans=d[i];

}

int main()
{
m=0;
t[m].u=;
t[m].v=;
t[m].w=;
m++;

}
~2015.9.5更新
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: