1. 程式人生 > 其它 >floyd && dijkstra

floyd && dijkstra

floyd
問題
用Floyd演算法求解下圖各個頂點的最短距離。寫出Floyd演算法的虛擬碼和給出距離矩
陣(頂點之間的最短距離矩陣)
在這裡插入圖片描述用Floyd演算法求解下圖各個頂點的最短距離。寫出Floyd演算法的虛擬碼和給出距離矩
陣(頂點之間的最短距離矩陣)
原理
floyd運用到了動態規劃的思想,求兩點之間最短的距離,分為經過k和不經過k的路徑,取兩者最短
虛擬碼:

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

矩陣:

0 2 5 4
2 0 3 4
5 3 0 1
4 4 1 0
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=105;
const int INF=0x3f3f3f3f;
int dp[N][N];
int n,m;
void init(){
    for
(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(j==i)dp[i][j]=0; else dp[i][j]=INF; } } } void floyd(){ for(int k=1;k<=n;k++){ for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ dp[i][j]=min(dp[i][j],dp[i][k]+
dp[k][j]); } } } } int main(){ while(cin>>n>>m&&n+m){ int u,v,w; init(); for(int i=1;i<=m;i++){ scanf("%d%d%d",&u,&v,&w); dp[u][v]=min(dp[u][v],w); } floyd(); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ printf("%d%c",dp[i][j],j==n?'\n':' '); } } printf("%d\n",dp[1][n]); } }

分析
floyd因為有很多計算是無效的所以演算法效率不高,複雜度為( n 3 n^3 n3);
dijkstra
問題
對於下圖使用Dijkstra演算法求由頂點a到頂點h的最短路徑。
在這裡插入圖片描述
原理
選擇一個起始點,選擇與它相連的最小路徑。然後如果原點到i點的權值和加i點到j點的權值小於已知原點到j點的權值和,則將其更新,按照這個步驟往下去,直到所有點都被訪問過

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<stack>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
#include<string>
#include<set>
#define Case int t;scanf("%d",&t);while(t--)
#define pi acos(-1)
#define eps 1e-8
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
const int M = 1e5 + 10;
const int inf = 0x3f3f3f3f;
const ll mod = 1e9+7;
struct edge{
	int from,to,w;
	edge(int a,int b,int c){from=a;to=b;w=c;}
};
vector<edge>e[M];
struct node{
	int id,dist;
	node(int u,int v){id=u,dist=v;}
	bool operator<(const node &a)const{
		return dist>a.dist;
	}
};
int n,m;
int dis[M];
bool done[M];
void dijkstra(){
	int s=1;
	for(int i=1;i<=n;i++){
		dis[i]=inf;
		done[i]=0;
	}
	dis[s]=0;
	priority_queue<node>q;
	q.push(node(s,dis[s]));
	while(!q.empty()){
		node u=q.top();
		q.pop();
		if(done[u.id])continue;
		done[u.id]=1;
		for(int i=0;i<e[u.id].size();i++){
			edge y=e[u.id][i];
			if(done[y.to])continue;
			if(dis[y.to]>y.w+u.dist){
				dis[y.to]=y.w+u.dist;
				q.push(node(y.to,dis[y.to]));
			}
		}
	}
	printf("%d\n",dis[n]);
}
void run() {
	while(~scanf("%d%d",&n,&m)&&n&&m){
		for(int i=1;i<=n;i++)e[i].clear();
		for(int i=1;i<=m;i++){
			int u,v,w;
			scanf("%d%d%d",&u,&v,&w);
			e[u].push_back(edge(u,v,w));
		}
		dijkstra();
	}
}
int main() {
//	Case
		run();
	return 0;
}

分析
Dijkstra演算法適用於計算正權圖(邊權為正)上的單源最短路,即從單個源點出發,到所有節點的最短路。該演算法同時適用於有向圖和無向圖。不適於環,複雜度為o( n 2 n^2 n2).
程式碼維護
https://github.com/kitalekita/kitalekita/blob/main/dijkstra.cpp
https://github.com/kitalekita/kitalekita/blob/main/floyd.cpp