图论 ----- 最短路径

来源:互联网 发布:江宁区广电网络营业厅 编辑:程序博客网 时间:2024/05/24 05:42

求最短路径应该是一个常考的知识点。所以我花了一些时间把它总结了下(可能不是很全)

 

 

求图的最短路主要有三种方法:

1.Dijkstra算法:

思想:

用一个dis数组去存储各点到起点的距离(即我们要求的结果),并将所有的元素

都初始化为该点到起点的直接边的距离。(如果没有直接边,则初始化为一个较

大的数;起点自身的dis初始化为0)。

用flag数组(bool)去标记每个点是否已找过。

接下来就是循环了:

{

找dis最小的,并且flag==false的节点x;

Flag[x]==true;

然后用x更新所有节点的dis:dis[j]=min(dis[j],dis[x]+tu[x][j]);//注:j是迭代器

//tu是邻接矩阵。

}

最后得到结果!!!

代码:

#include <iostream>

#include <cstring>

#include <algorithm>

using namespace std;

const int maxn=1000;

const int INF=99999;

int tu[maxn][maxn];

int dis[maxn];

bool flag[maxn];

int n;

int m;

void read()

{

memset(tu,0,sizeof(tu));

memset(dis,0,sizeof(dis));

memset(flag,false,sizeof(flag));

cin>>n>>m;

for(int i=0;i<n;i++)

{

for(int j=0;j<n;j++)

{

if(i!=j)

{

tu[i][j]=INF;

}

else

tu[i][j]=0;

}

}

for(int i=0;i<m;i++)

{

int x,y,z;

cin>>x>>y>>z;

tu[x-1][y-1]=z;

tu[y-1][x-1]=z;

}

}

void Dijkstra(int start)

{

//初始化

for(int i=0;i<n;i++)

{

dis[i]=tu[start][i];        

}

//循环        

for(int i=0;i<n;i++)

{

int minl=INF;

int x=-1;

for(int j=0;j<n;j++)

{

if(dis[j]<minl&&flag[j]==false)

{

minl=dis[j];

x=j;

}        

}

if(x!=-1)

{

flag[x]=true;

for(int j=0;j<n;j++)

{

dis[j]=min(dis[j],dis[x]+tu[x][j]);

}

}

}

}

int main()

{

read();

cout<<"input start andend"<<endl;

int start,end;

cin>>start>>end;

Dijkstra(start-1);

cout<<dis[end-1];

return 0;

}


 

2.SPFA算法:

思想:

还是用个dis数组去存储各点到起点的距离(即我们要求的结果),并将所有的元素

都初始化为该点到起点的直接边的距离

要开一个队列q(int)

用flag数组(bool)去标记节点是否在队列中。

用cot数组(int)去记录节点入队列的次数。全部初始化为0;

 

然后,将起点入队列;将其的flag变为true;cot变为1;

当队列不空时循环:

{

把一个点出队列,赋值给i;

flag[i]=false;

遍历每个与i相连的点:j

{

如果(dis[j]>dis[i]+tu[i][j])

{

dis[j]=dis[i]+tu[i][j];

如果(flag[j]==false)

{

将j入队列;

flag[j]=true;

cot[j]++;

如果(cot[j]>节点总个数)

{

//有负环

退出;

}

}

}

}

}

如果没有负权环的话,最后能得到结果。

代码:

#include<iostream>

#include<cstring>

#include<algorithm>

#include<queue>

using namespace std;

const int maxn=1000;

const int INF=99999;

int tu[maxn][maxn];

int dis[maxn];

bool flag[maxn];

int cot[maxn];

int n;

int m;

void read()

{

memset(tu,0,sizeof(tu));

memset(dis,0,sizeof(dis));

memset(cot,0,sizeof(cot));

memset(flag,false,sizeof(flag));

cin>>n>>m;

for(int i=0;i<n;i++)

{

for(int j=0;j<n;j++)

{

if(i!=j)

{

tu[i][j]=INF;

}

else

tu[i][j]=0;

}

}

for(int i=0;i<m;i++)

{

int x,y,z;

cin>>x>>y>>z;

tu[x-1][y-1]=z;

tu[y-1][x-1]=z;

}

}

void SPFA(int start)

{

for(int i=0;i<n;i++)

dis[i]=INF;

dis[start]=0;

queue<int> q;

q.push(start);

flag[start]=true;

cot[start]+=1;

while(!q.empty())

{

int i;

i=q.front();

flag[i]=false;

q.pop();

for(int j=0;j<n;j++)

{

if(tu[i][j]!=INF)

{

if(dis[j]>dis[i]+tu[i][j])

{

dis[j]=dis[i]+tu[i][j];

if(flag[j]==false)

{

q.push(j);

flag[j]=true;

cot[j]+=1;

if(cot[j]>n)

return ;

}

}

}

}

}

}

int main()

{

read();

cout<<"input start andend"<<endl;

int start,end;

cin>>start>>end;

SPFA(start-1);

cout<<dis[end-1];

return 0;;

}



3.Floyd算法:

思想:

只要一个dis数组。

然后多重循环暴力!!!

代码:

#include <iostream>

#include <cstring>

#include <algorithm>

using namespace std;

const int maxn=1000;

const int INF=99999;

int tu[maxn][maxn];

int dis[maxn];

int n;

int m;

void read()

{

memset(tu,0,sizeof(tu));

memset(dis,0,sizeof(dis));

cin>>n>>m;

for(int i=0;i<n;i++)

{

for(int j=0;j<n;j++)

{

if(i!=j)

{

tu[i][j]=INF;

}

else

tu[i][j]=0;

}

}

for(int i=0;i<m;i++)

{

int x,y,z;

cin>>x>>y>>z;

tu[x-1][y-1]=z;

tu[y-1][x-1]=z;

}

}

void floyd(int start)

{

for(int i=0;i<n;i++)

{

dis[i]=tu[start][i];

}

for(int i=0;i<n;i++)

{

for(int j=0;j<n;j++)

{

dis[i]=min(dis[i],dis[j]+tu[i][j]);

}

}

}

int main()

{

read();

cout<<"input start andend"<<endl;

int start,end;

cin>>start>>end;

floyd(start-1);

cout<<dis[end-1];

return 0;

}



0 0