1. 程式人生 > >最短路的另外兩種演算法

最短路的另外兩種演算法

//由於Dijksrta演算法,當圖中的權值邊含有負值時,求不出最短路
//原因是因為,每個結點只能入隊一次,被訪問過後永久標記,所以,當存在一條負的權值邊
//使得某一個節點到源點s的距離更短時,無法再一次呼叫此結點更新其餘的點
//所以下面介紹另外的兩種演算法
//Bellman-Ford演算法:如果存在一條最短路,一定不存在環
//如果有環,則環程式會在環中迴圈,無法跑出來,如果存在最短路,一定沒有負環 
//因為一直在負環當中跑,最短路的路徑會一直減小,沒有一個最小值
//下面先上程式碼:(有一些地方還沒明白,只能先盲敲一遍了)
bool bellman ford(int s)
{
    queue<int> Q;
    memset(inq,
0,sizeof(inq));//inq陣列記錄結點有沒有被訪問過 memset(cnt,0;sizeof(cnt));//cnt陣列記錄每一個結點出現的次數,由於負邊的存在,一個結點可被訪問多次 //如果某一個結點被訪問的次數大於n,則一定說明一定含有環 for(int i=0;i<n;i++) d[i]=inf; d[s]=0; inq[s]=true; Q.push(s); while(!Q.empty()) { int u=Q.front(); Q.pop(); inq[u]
=false; for(int i=0;i<G.size();i++) Edge& e=edges[G[u][i]]; if(d[u]<inf&&d[e.to]>d[u]+e.dist) { d[e.to]=d[u]+e.dist; p[e.to]=G[u][i]; if(!inq[e.to]) { Q.push(e.to) inq[e.to]
=true; if(++cnt[e.to]>n) return false; } } } return true; } //Floy演算法時間複雜度O(n*n*n),基於動態規劃 for(int k=0;k<n;k++) for(int i=;i<n;i++) for(int j=0;j<n;j++) d[i][j]=min(d[i][j],d[i][k]+d[k][j]); //如果不關心路徑的長度,而只要路徑是否連通 //則程式碼改寫成d[i][j]=d[i][j]||(d[i][k]&&d[k][j]) //初始化時,初始化d[i][j]為inf要注意