プログラミング
 Computer >> コンピューター >  >> プログラミング >> プログラミング

単一ソースの最短経路、任意の重み


単一ソース最短経路アルゴリズム(任意の重みが正または負の場合)も知られています。ベルマンフォードアルゴリズムは、ソース頂点から他の頂点までの最小距離を見つけるために使用されます。このアルゴリズムとダイクストラのアルゴリズムの主な違いは、ダイクストラのアルゴリズムでは負の重みを処理できないことですが、ここでは簡単に処理できます。

単一ソースの最短経路、任意の重み

Bellman-Fordアルゴリズムは、ボトムアップ方式で距離を検出します。最初に、パスにエッジが1つしかない距離を見つけます。その後、パスの長さを増やして、考えられるすべての解決策を見つけます。

入力 −グラフのコストマトリックス:

0 6 ∞ 7 ∞
∞ 0 5 8 -4
∞ -2 0 ∞ ∞
∞ ∞ -3 0 9
2 ∞ 7 ∞ 0

出力 −ソース頂点:2
頂点:0 1 2 3 4
距離:-4 -2 0 3 -6
Pred:4 2 -1 0 1
グラフには負のエッジサイクルはありません

アルゴリズム

bellmanFord(dist、pred、source)

入力 −距離リスト、先行リスト、およびソース頂点。

出力 −真、負のサイクルが見つかった場合。

Begin
   iCount := 1
   maxEdge := n * (n - 1) / 2 //n is number of vertices
   for all vertices v of the graph, do
      dist[v] := ∞
      pred[v] := ϕ
   done
   dist[source] := 0
   eCount := number of edges present in the graph
   create edge list named edgeList
   while iCount < n, do
   for i := 0 to eCount, do
      if dist[edgeList[i].v] > dist[edgeList[i].u] + (cost[u,v] for edge i)
         dist[edgeList[i].v] > dist[edgeList[i].u] + (cost[u,v] for edge i)
         pred[edgeList[i].v] := edgeList[i].u
      done
   done
   iCount := iCount + 1
   for all vertices i in the graph, do
      if dist[edgeList[i].v] > dist[edgeList[i].u] + (cost[u,v] for edge i), then
         return true
      done
   return false
End

例(C ++)

#include<iostream>
#include<iomanip>
#define V 5
#define INF 999
using namespace std;
//Cost matrix of the graph (directed) vertex 5
int costMat[V][V] = {
   {0, 6, INF, 7, INF},
   {INF, 0, 5, 8, -4},
   {INF, -2, 0, INF, INF},
   {INF, INF, -3, 0, 9},
   {2, INF, 7, INF, 0}
};
typedef struct{
   int u, v, cost;
}edge;
int isDiagraph(){
   //check the graph is directed graph or not
   int i, j;
   for(i = 0; i<V; i++){
      for(j = 0; j<V; j++){
         if(costMat[i][j] != costMat[j][i]){
            return 1;//graph is directed
         }
      }
   }
   return 0;//graph is undirected
}
int makeEdgeList(edge *eList){
   //create edgelist from the edges of graph
   int count = -1;
   if(isDiagraph()){
      for(int i = 0; i<V; i++){
         for(int j = 0; j<V; j++){
            if(costMat[i][j] != 0 && costMat[i][j] != INF){
               count++;//edge find when graph is directed
               eList[count].u = i; eList[count].v = j;
               eList[count].cost = costMat[i][j];
            }
         }
      }
   }else{
      for(int i = 0; i<V; i++){
         for(int j = 0; j<i; j++){
            if(costMat[i][j] != INF){
               count++;//edge find when graph is undirected
               eList[count].u = i; eList[count].v = j;
               eList[count].cost = costMat[i][j];
            }
         }
      }
   }
   return count+1;
}
int bellmanFord(int *dist, int *pred,int src){
   int icount = 1, ecount, max = V*(V-1)/2;
   edge edgeList[max];
   for(int i = 0; i<V; i++){
      dist[i] = INF;//initialize with infinity
      pred[i] = -1;//no predecessor found.
   }
   dist[src] = 0;//for starting vertex, distance is 0
   ecount = makeEdgeList(edgeList); //edgeList formation
   while(icount < V){ //number of iteration is (Vertex - 1)
      for(int i = 0; i<ecount; i++){
         if(dist[edgeList[i].v] > dist[edgeList[i].u] + costMat[edgeList[i].u][edgeList[i].v]){
            //relax edge and set predecessor
            dist[edgeList[i].v] = dist[edgeList[i].u] + costMat[edgeList[i].u][edgeList[i].v];
            pred[edgeList[i].v] = edgeList[i].u;
         }
      }
      icount++;
   }
   //test for negative cycle
   for(int i = 0; i<ecount; i++){
      if(dist[edgeList[i].v] > dist[edgeList[i].u] + costMat[edgeList[i].u][edgeList[i].v]){
         return 1;//indicates the graph has negative cycle
      }
   }
   return 0;//no negative cycle
}
void display(int *dist, int *pred){
   cout << "Vert: ";
   for(int i = 0; i<V; i++)
      cout <<setw(3) << i << " ";
   cout << endl;
   cout << "Dist: ";
   for(int i = 0; i<V; i++)
      cout << setw(3) << dist[i] << " ";
   cout << endl;
   cout << "Pred: ";
   for(int i = 0; i<V; i++)
      cout << setw(3) << pred[i] << " ";
   cout << endl;
}
int main(){
   int dist[V], pred[V], source, report;
   source = 2;
   report = bellmanFord(dist, pred, source);
   cout << "Source Vertex: " << source<<endl;
   display(dist, pred);
   if(report)
      cout << "The graph has a negative edge cycle" << endl;
   else
      cout << "The graph has no negative edge cycle" << endl;
}

出力

Source Vertex: 2
Vert: 0 1 2 3 4
Dist: -4 -2 0 3 -6
Pred: 4 2 -1 0 1
The graph has no negative edge cycle

  1. C++でマンハッタン距離に等しい距離のパスをカウントします

    2D座標系上の2つの点を(x1、y1)および(x2、y2)として表す変数x1、x2、y1、y2が与えられます。目標は、これら2つのポイント間のマンハッタン距離に等しい距離を持つすべてのパスを見つけることです。 マンハッタン距離 マンハッタン2点(x1、y1)と(x2、y2)の間の距離は- MD =| x1 – x2 | + | y1 – y2 | A =| x1 –x2|を取りましょうおよびB=| y1 – y2 | マンハッタン距離がMDに等しいすべてのパスでは、エッジが(A + B)としてカウントされます。水平エッジとB垂直エッジ。したがって、2つのグループに分割された(A +

  2. C++のツリー内の2つの交差しないパスの最大積

    この問題では、n個のノードを持つ無向接続ツリーTが与えられます。私たちのタスクは、C++のツリー内の2つの交差しないパスの最大積を見つけるプログラムを作成することです。 問題の説明 −ツリー内の交差しない2つのパスの最大積を見つける。興味のないすべてのパスを見つけてから、それらの長さの積を見つけます。 問題を理解するために例を見てみましょう 入力 グラフ- 出力 8 説明 考慮される交差しないパスはC-A-B およびF-E-D-G-H 。 長さは2と4です。Product=8。 ソリューションアプローチ この問題の解決策は、DFSを使用してツリーをトラバースすることです。そ