簡體   English   中英

如何打印圖中兩個頂點之間的最短路徑?

[英]How can I print the shortest path between two vertices in a graph?

我有一個 Djikstra 算法的工作實現,它計算任意兩個節點之間的最短路徑的長度。 但是如果我需要找到實際路徑,我該如何打印呢? 謝謝!

void djikstra( graph * mygraph )
{
    int dist[100] = {INT_MAX};
    int i;
    //int parent[mygraph->vertices] = {-99};
    for ( i = 0; i < 100; i++ )
        dist[i] = INT_MAX;
    bool arr[100];
    for ( i = 0; i < 100; i++ )
        arr[i] = false;
    int foo;
    cout<<"Enter the source vertex\n";
    cin>>foo;
    dist[foo] = 0;  
    vector<int> bar;
    while (bar.size() != mygraph->vertices)
    {
        int node = findmin(dist,mygraph->vertices,arr);
        arr[node] = true; // so that again and again same node having minimum distance is not returned
        bar.push_back(node);
        auto it = mygraph->edges[node].begin();
        while (it != mygraph->edges[node].end())
        {
            relax(node,it->first,it->second,dist); // here, it->first represents the node and it->second represents the weight
            it++;
        }
    }
    cout<<"Vertex\t"<<"Distance from source\n";
    for ( i = 0; i < mygraph->vertices; i++ )
    {
        cout<<i<<"\t"<<dist[i]<<"\n";
    }   
    cout<<"\n";
    return;
}

void relax ( int node, int a, int w, int dist[] )
{
    if (dist[a] > dist[node] + w)
    {
        dist[a] = dist[node] + w;
    }
}

您還需要保留從節點映射到其“父節點”的映射。

在這張地圖中,鍵是一個節點,值是用來到達這張地圖的節點。
顯然,源將成為這張地圖的根。

這是通過添加:

parentMap[a] = node;

在松弛步驟中:

void relax ( int node, int a, int w, int dist[] )
{
    if (dist[a] > dist[node] + w)
    {
        dist[a] = dist[node] + w;
        parentMap[a] = node;
    }
}

一旦你有了這張地圖,獲取路徑就非常容易了,通過以下方式完成:

int current = target;
while (current != source) { 
   cout << current << ' ';
   current = parentMap[current];
}
cout << current << ' ';

請注意,上面以相反的順序打印路徑。 您可以使用列表(並將元素添加到其前面而不是打印元素)以正確順序獲取路徑。

您可以通過父節點追溯您的路徑。

#include<bits/stdc++.h>

using namespace std;

class solution{
public:
    void printPath(vector<int> parent, int source, int dest)
    {
        stack<int> st;
        int final = dest;
        while(parent[dest] != source)
        {
            dest = parent[dest];
            st.push(dest);
        }
        cout<<source<<"->";
        while(!st.empty())
        {
            cout<<st.top()<<"->";
            st.pop();
        }
        cout<<final<<endl;
    }

    void shortestPath(int V, vector<pair<int, int>> G[], int source, int dest)
    {
        vector<int> dist(V, INT_MAX);
        dist[source] = 0;
        queue<int> q;
        q.push(source);
        vector<int> parent(V, -1);
        parent[source] = source;
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            for(auto node: G[u])
            {
                int v = node.first;
                int wt = node.second;
                if(dist[v] > dist[u]+wt)
                {
                    dist[v] = dist[u]+wt;
                    q.push(v);
                    parent[v] = u;
                }
            }
        }

        cout<<"Cost to reach destination: "<<dist[dest]<<"\n";
        printPath(parent, source, dest);
    }
};

int main(){
    int V, E, source, dest;
    cout<<"Enter # of Vertex : ";
    cin>>V;
    cout<<"Enter # of Edges : ";
    cin>>E;
    int u, v, wt;
    cout<<"Add Edges ->\n";
    vector<pair<int, int>> adj[V];
    while(E--)
    {
        cin>>u>>v>>wt;
        adj[u].push_back(make_pair(v, wt));
    }
    cout<<"Enter Source : ";
    cin>>source;
    cout<<"Enter Destination :";
    cin>>dest;
    solution* obj = new solution;
    obj->shortestPath(V, adj, source, dest);
    return 0;
}

上述代碼的輸出如下所示,

Enter # of Vertex : 6
Enter # of Edges : 8
Add Edges ->
0 1 2
1 2 5
2 3 5
3 4 5
4 1 50
4 5 600
1 5 1000
2 4 1
Enter Source : 0
Enter Destination :5
Cost to reach destination: 608
0->1->2->4->5

Shortest Path-Printing using Dijkstra's Algorithm for Graph(這里是為無向圖實現的。以下代碼打印從 source_node 到圖中所有其他節點的最短距離。

它還打印從源節點到用戶請求的節點的最短路徑。 假設,您需要在圖中找到從AB的最短路徑。 然后輸入A作為源節點, B作為目的節點。

代碼

#include<bits/stdc++.h>
using namespace std;
#define INF (unsigned)!((int)0)

const int MAX=2e4;
vector<pair<int,int>> graph[MAX];

bool visit[MAX];
int dist[MAX];

multiset<pair<int,int>> s;
int parent[MAX];                                 // used to print the path

int main(){
    memset(visit,false,sizeof(visit));
    memset(dist,INF,sizeof(dist));
    memset(parent,-1,sizeof(parent));

    int nodes,edges;        cin>>nodes>>edges;
    for(auto i=0;i<edges;++i){
        int a,b,w;
        cin>>a>>b>>w;
        graph[a].push_back(make_pair(b,w));
        graph[b].push_back(make_pair(a,w));   //Comment it to make the Directed Graph
    }
    int source_node;    cin>>source_node;
    dist[source_node]=0;
    s.insert(make_pair(0,source_node));

    while(!s.empty()){
        pair<int,int> elem=*s.begin();
        s.erase(s.begin());
        int node=elem.second;
        if(visit[node])continue;
        visit[node]=true;
        for(auto i=0;i<graph[node].size();++i){
            int dest=graph[node][i].first;
            int w=graph[node][i].second;
            if(dist[node]+w<dist[dest]){
                dist[dest]=dist[node]+w;
                parent[dest]=node;
                s.insert(make_pair(dist[dest],dest));
            }
        }
    }
    cout<<"NODE"<<"         "<<"DISTANCE"<<endl;
    for(auto i=1;i<=nodes;++i){
        cout<<i<<"         "<<dist[i]<<endl;
    }
    /*----PRINT SHORTEST PATH FROM THE SOURCE NODE TO THE NODE REQUESTED-------*/
    int node_for_path;      cin>>node_for_path;
    int dest_node=node_for_path;
    stack<int> path;
    while(parent[node_for_path]!=source_node){
        path.push(node_for_path);
        node_for_path=parent[node_for_path];
    }
    path.push(node_for_path);
    path.push(source_node);
    cout<<"Shortest Path from "<<source_node<<"to "<<dest_node<<":"<<endl;
    while(!path.empty()){
        if(path.size()==1) cout<<path.top();
        else cout<<path.top()<<"->";
        path.pop();
    }
    return 0;
}
/*TEST CASE*/
9 14        //---NODES,EDGES---
1 2 4       //---START,END,WEIGHT---FOR THE NO OF EDGES
2 3 8
3 4 7
4 5 9
5 6 10
6 7 2
7 8 1
8 1 8
2 8 11
8 9 7
9 7 6
9 3 2
6 3 4
4 6 14
1           //---SOURCE_NODE
5           //-----NODE TO WHICH PATH IS REQUIRED
---END---*/

希望能幫助到你

基於上面的@Dipesh Kurasau,我在下面做了一些代碼:輸出為:總距離=400。 路徑:0 5. 如果注釋掉 v0.adjacents.emplace(&v5, 400); 您會得到與@Dipesh Kurasau 相同的結果。

#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <queue>
#include <stack>

using namespace std;

class Vertex
{
public:
    Vertex(int i) : id(i) {}
    int id;
    int toSrcVertex = INT_MAX; // initial distance from this vertex to the source vertex
    Vertex* prev = NULL;       // point to the previous vertex leading to the source vertex making the shortest path
    unordered_map<Vertex*, int> adjacents; //adjacent vertex and its distance;
};

void printPath(Vertex* destination)
{
    cout << "total distance =" << destination->toSrcVertex << endl;
    cout << "Path:" << endl;
    stack<Vertex*> reversed;

    while (destination)
    {
        reversed.push(destination);
        destination = destination->prev;
    }

    while (!reversed.empty())
    {
        Vertex* t = reversed.top();
        reversed.pop();
        cout << t->id << " ";
    }

    cout << "\ndone" << std::flush << endl;
}

void shortest(Vertex* src, Vertex* dest)
{
    src->toSrcVertex = 0;
    unordered_set<Vertex*> q;
    q.insert(src);

    unordered_set<Vertex*> visited;

    while (!q.empty())
    {
        Vertex* u = *(q.begin());
        q.erase(q.begin());

        if (q.empty() && u == dest)
        {
            // target reached, no more search
            return;
        }

        // vistit all adjacents of Vertex u
        for(auto& adj : u->adjacents)
        {
            Vertex* adjVertex = adj.first;

            if (visited.find(adjVertex) != visited.end()) continue;

            int distance = adj.second;

            int distanceFromUtoAdjVertex = distance + u->toSrcVertex;

            if (distanceFromUtoAdjVertex < adjVertex->toSrcVertex)
            {
                adjVertex->toSrcVertex = distanceFromUtoAdjVertex;
                adjVertex->prev = u;
                q.insert(adjVertex);
            }
        }

        visited.insert(u);
    }

    printPath(dest);
}

int main()
{
    // construct vertices
    Vertex v0(0);
    Vertex v1(1);
    Vertex v2(2);
    Vertex v3(3);
    Vertex v4(4);
    Vertex v5(5);

    // build adjacents (neighboured vertex and distance)
    v0.adjacents.emplace(&v1, 2);
    v0.adjacents.emplace(&v5, 400);

    v1.adjacents.emplace(&v0, 2);
    v1.adjacents.emplace(&v2, 5);
    v1.adjacents.emplace(&v4, 50);
    v1.adjacents.emplace(&v5, 1000);

    v2.adjacents.emplace(&v1, 5);
    v2.adjacents.emplace(&v3, 5);
    v2.adjacents.emplace(&v4, 1);

    v3.adjacents.emplace(&v2, 5);
    v3.adjacents.emplace(&v4, 5);

    v4.adjacents.emplace(&v2, 1);
    v4.adjacents.emplace(&v3, 5);
    v4.adjacents.emplace(&v1, 50);
    v4.adjacents.emplace(&v5, 600);

    v5.adjacents.emplace(&v1, 1000);
    v5.adjacents.emplace(&v4, 600);

    shortest(&v0, &v5);

    std::cout << "Hello World!\n" << flush << endl;;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM