Dijkstra算法:
思想:找到距離原點最近的一個頂點,然后以該點為中心進行擴展,最終得到源點到其余各點的最短路徑。
缺點:無法解決帶負邊的圖論問題。
輸入樣例:
6 9 1 (6個點 9條邊 起點為1)
1 2 1
1 3 12
2 3 9
2 4 3
3 5 5
4 3 4
4 5 13
4 6 15
5 6 4
輸出樣例:
0 1 8 4 13 17 (源點到各點的最短距離)
#include <cstdio>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <math.h>
#include <vector>
using namespace std;
const int inf=999999;//0x7fffff
const long long mod=1e9+7;
const double PI=acos(-1);
#include <string.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <math.h>
#include <vector>
using namespace std;
const int inf=999999;//0x7fffff
const long long mod=1e9+7;
const double PI=acos(-1);
int n,m;
int ans=9999999;
bool vis[105];
int dis[105];
int ans=9999999;
bool vis[105];
int dis[105];
struct node{
int u;
int w;
node(int uu,int ww){
u=uu;
w=ww;
}
};
vector<node> v[105];
void Dijkstra(int s){ //Dijkstra算法為單源最短路徑算法 s 為起點
memset(dis,inf,sizeof(dis)); //dis數組表示起點 s 到每個點的最小路徑
dis[s]=0;
int min,minp;
for(int i=1;i<=n;i++){ //遍歷dis數組的每一個最短路徑
min=inf;
for(int j=1;j<=n;j++){
if(!vis[j]&&dis[j]<min){ //尋找並記錄此時dis表的最短路徑的值和距離
min=dis[j];
minp=j;
}
}
vis[minp]=1;
for(int u=0;u<v[minp].size();u++){ //尋找此時最短路徑的點可到的點 並更新該點的最短路徑
node no=v[minp][u];
if(!vis[no.u]&&dis[no.u]>dis[minp]+no.w){
dis[no.u]=dis[minp]+no.w;
}
}
}
}
int main()
{
int x,y,value,s;
cin>>n>>m>>s;
for(int i=1;i<=n;i++){
dis[i]=inf;
}
for(int i=0;i<m;i++){
cin>>x>>y>>value;
v[x].push_back(node(y,value));
}
Dijkstra(s); //s 為起點
for(int i=1;i<=n;i++){ //輸出s 到各個點的最短路徑
cout<<dis[i]<<" ";
}
return 0;
}
int u;
int w;
node(int uu,int ww){
u=uu;
w=ww;
}
};
vector<node> v[105];
void Dijkstra(int s){ //Dijkstra算法為單源最短路徑算法 s 為起點
memset(dis,inf,sizeof(dis)); //dis數組表示起點 s 到每個點的最小路徑
dis[s]=0;
int min,minp;
for(int i=1;i<=n;i++){ //遍歷dis數組的每一個最短路徑
min=inf;
for(int j=1;j<=n;j++){
if(!vis[j]&&dis[j]<min){ //尋找並記錄此時dis表的最短路徑的值和距離
min=dis[j];
minp=j;
}
}
vis[minp]=1;
for(int u=0;u<v[minp].size();u++){ //尋找此時最短路徑的點可到的點 並更新該點的最短路徑
node no=v[minp][u];
if(!vis[no.u]&&dis[no.u]>dis[minp]+no.w){
dis[no.u]=dis[minp]+no.w;
}
}
}
}
int main()
{
int x,y,value,s;
cin>>n>>m>>s;
for(int i=1;i<=n;i++){
dis[i]=inf;
}
for(int i=0;i<m;i++){
cin>>x>>y>>value;
v[x].push_back(node(y,value));
}
Dijkstra(s); //s 為起點
for(int i=1;i<=n;i++){ //輸出s 到各個點的最短路徑
cout<<dis[i]<<" ";
}
return 0;
}
Bellman_Floyd算法:
思路:將起使元素入隊,隊首元素出隊,遍歷隊首元素連接的節點,每次判斷能不能通過隊首元素使起使元素到此時遍歷的節點,使最短路徑變小並更新,到隊列為空為止。
有點類似於寬度優先搜索,只是寬度優先搜索出隊后不再入隊,該算法需要不斷更新最短路徑,可能需要重新入隊。
優點:可以解決帶負邊的問題。
輸入樣例:
5 7 1 (5個點 7條邊 起點元素1)
1 2 2
1 5 10
2 3 3
2 5 7
3 4 4
4 5 5
5 3 6
輸出樣例:
0 2 5 9 9(起點到各個點的最短路徑)
#include <cstdio> #include <string.h> #include <iostream> #include <algorithm> #include <sstream> #include <math.h> #include <vector> #include <queue> using namespace std; const int inf=999999;//0x7fffff const long long mod=1e9+7; const double PI=acos(-1); int n,m; int ans=9999999; bool vis[105]; int dis[105],u[105]; struct node{ int v; int w; node(int vv,int ww){ v=vv; w=ww; } }; vector<node> v[105]; queue<int> q; void Bellman_Floyd(int s){ memset(dis,inf,sizeof(dis)); //初始化設置所有節點都不可達 dis[s]=0; vis[s]=1; q.push(s); while(!q.empty()){ int no = q.front(); // no隊首元素序號 nd隊首元素連接節點 q.pop(); for(int i=0;i<v[no].size();i++){ //每次遍歷隊首節點的連接的節點 判斷通過隊首節點能否使到達連接節點的最短路徑變小並更新 node nd=v[no][i]; if(dis[nd.v]>dis[no]+nd.w){ dis[nd.v]=dis[no]+nd.w; if(!vis[nd.v]){ //此時隊首相連節點不在隊列中 需要添加隊列中並置為訪問 vis[nd.v]=1; q.push(nd.v); } } }
vis[no]=0; } } int main() { int x,y,value,s; cin>>n>>m>>s; for(int i=1;i<=m;i++){ cin>>x>>y>>value; v[x].push_back(node(y,value)); } Bellman_Floyd(s); for(int i=1;i<=n;i++){ cout<<dis[i]<<" "; } return 0; }