1. 程式人生 > >有向無環圖求最長路

有向無環圖求最長路

[cpp] view plain copy print?
  1. // A C++ program to find single source longest distances in a DAG
  2. #include <iostream>
  3. #include <list>
  4. #include <stack>
  5. #include <limits.h>
  6. #define NINF INT_MIN
  7. usingnamespace std;  
  8. //圖通過鄰接表來描述。鄰接表中的每個頂點包含所連線的頂點的資料,以及邊的權值。
  9. class AdjListNode  
  10. {  
  11.     int v;  
  12.     int weight;  
  13. public:  
  14.     AdjListNode(int _v, int _w)  { v = _v;  weight = _w;}  
  15.     int getV()       {  return v;  }  
  16.     int getWeight()  {  return weight; }  
  17. };  
  18. // Class to represent a graph using adjacency list representation
  19. class Graph  
  20. {  
  21.     int V;    // No. of vertices’
  22.     // Pointer to an array containing adjacency lists
  23.     list<AdjListNode> *adj;  
  24.     // A function used by longestPath
  25.     void topologicalSortUtil(int v, bool visited[], stack<int> &Stack);  
  26. public:  
  27.     Graph(int V);   // Constructor
  28.     // function to add an edge to graph
  29.     void addEdge(int u, int v, int weight);  
  30.     // Finds longest distances from given source vertex
  31.     void longestPath(int s);  
  32. };  
  33. Graph::Graph(int V) // Constructor
  34. {  
  35.     this->V = V;  
  36.     adj = new list<AdjListNode>[V];  
  37. }  
  38. void Graph::addEdge(int u, int v, int weight)  
  39. {  
  40.     AdjListNode node(v, weight);  
  41.     adj[u].push_back(node); // Add v to u’s list
  42. }  
  43. // 通過遞迴求出拓撲序列. 詳細描述,可參考下面的連結。
  44. // http://www.geeksforgeeks.org/topological-sorting/
  45. void Graph::topologicalSortUtil(int v, bool visited[], stack<int> &Stack)  
  46. {  
  47.     // 標記當前頂點為已訪問
  48.     visited[v] = true;  
  49.     // 對所有鄰接點執行遞迴呼叫
  50.     list<AdjListNode>::iterator i;  
  51.     for (i = adj[v].begin(); i != adj[v].end(); ++i)  
  52.     {  
  53.         AdjListNode node = *i;  
  54.         if (!visited[node.getV()])  
  55.             topologicalSortUtil(node.getV(), visited, Stack);  
  56.     }  
  57.     // 當某個點沒有鄰接點時,遞迴結束,將該點存入棧中。
  58.     Stack.push(v);  
  59. }  
// A C++ program to find single source longest distances in a DAG
#include <iostream>
#include <list>
#include <stack>
#include <limits.h>
#define NINF INT_MIN
using namespace std;
 
//圖通過鄰接表來描述。鄰接表中的每個頂點包含所連線的頂點的資料,以及邊的權值。
class AdjListNode
{
    int v;
    int weight;
public:
    AdjListNode(int _v, int _w)  { v = _v;  weight = _w;}
    int getV()       {  return v;  }
    int getWeight()  {  return weight; }
};
 
// Class to represent a graph using adjacency list representation
class Graph
{
    int V;    // No. of vertices’
 
    // Pointer to an array containing adjacency lists
    list<AdjListNode> *adj;
 
    // A function used by longestPath
    void topologicalSortUtil(int v, bool visited[], stack<int> &Stack);
public:
    Graph(int V);   // Constructor
 
    // function to add an edge to graph
    void addEdge(int u, int v, int weight);
 
    // Finds longest distances from given source vertex
    void longestPath(int s);
};
 
Graph::Graph(int V) // Constructor
{
    this->V = V;
    adj = new list<AdjListNode>[V];
}
 
void Graph::addEdge(int u, int v, int weight)
{
    AdjListNode node(v, weight);
    adj[u].push_back(node); // Add v to u’s list
}
 
// 通過遞迴求出拓撲序列. 詳細描述,可參考下面的連結。
// http://www.geeksforgeeks.org/topological-sorting/
void Graph::topologicalSortUtil(int v, bool visited[], stack<int> &Stack)
{
    // 標記當前頂點為已訪問
    visited[v] = true;
 
    // 對所有鄰接點執行遞迴呼叫
    list<AdjListNode>::iterator i;
    for (i = adj[v].begin(); i != adj[v].end(); ++i)
    {
        AdjListNode node = *i;
        if (!visited[node.getV()])
            topologicalSortUtil(node.getV(), visited, Stack);
    }
 
    // 當某個點沒有鄰接點時,遞迴結束,將該點存入棧中。
    Stack.push(v);
}

[cpp] view plain copy print?
  1. // 根據傳入的頂點,求出到到其它點的最長路徑. longestPath使用了
  2. // topologicalSortUtil() 方法獲得頂點的拓撲序。
  3. void Graph::longestPath(int s)  
  4. {  
  5.     stack<int> Stack;  
  6.     int dist[V];  
  7.     // 標記所有的頂點為未訪問
  8.     bool *visited = newbool[V];  
  9.     for (int i = 0; i < V; i++)  
  10.         visited[i] = false;  
  11.     // 對每個頂點呼叫topologicalSortUtil,最終求出圖的拓撲序列存入到Stack中。
  12.     for (int i = 0; i < V; i++)  
  13.         if (visited[i] == false)  
  14.             topologicalSortUtil(i, visited, Stack);  
  15.     //初始化到所有頂點的距離為負無窮
  16.     //到源點的距離為0
  17.     for (int i = 0; i < V; i++)  
  18.         dist[i] = NINF;  
  19.     dist[s] = 0;  
  20.     // 處理拓撲序列中的點
  21.     while (Stack.empty() == false)  
  22.     {  
  23.         //取出拓撲序列中的第一個點
  24.         int u = Stack.top();  
  25.         Stack.pop();  
  26.         // 更新到所有鄰接點的距離
  27.         list<AdjListNode>::iterator i;  
  28.         if (dist[u] != NINF)  
  29.         {  
  30.           for (i = adj[u].begin(); i != adj[u].end(); ++i)  
  31.              if (dist[i->getV()] < dist[u] + i->getWeight())  
  32.                 dist[i->getV()] = dist[u] + i->getWeight();  
  33.         }  
  34.     }  
  35.     // 列印最長路徑
  36.     for (int i = 0; i < V; i++)  
  37.         (dist[i] == NINF)? cout << "INF ": cout << dist[i] << " ";  
  38. }  
// 根據傳入的頂點,求出到到其它點的最長路徑. longestPath使用了
// topologicalSortUtil() 方法獲得頂點的拓撲序。
void Graph::longestPath(int s)
{
    stack<int> Stack;
    int dist[V];
 
    // 標記所有的頂點為未訪問
    bool *visited = new bool[V];
    for (int i = 0; i < V; i++)
        visited[i] = false;
 
    // 對每個頂點呼叫topologicalSortUtil,最終求出圖的拓撲序列存入到Stack中。
    for (int i = 0; i < V; i++)
        if (visited[i] == false)
            topologicalSortUtil(i, visited, Stack);
 
    //初始化到所有頂點的距離為負無窮
    //到源點的距離為0
    for (int i = 0; i < V; i++)
        dist[i] = NINF;
    dist[s] = 0;
 
    // 處理拓撲序列中的點
    while (Stack.empty() == false)
    {
        //取出拓撲序列中的第一個點
        int u = Stack.top();
        Stack.pop();
 
        // 更新到所有鄰接點的距離
        list<AdjListNode>::iterator i;
        if (dist[u] != NINF)
        {
          for (i = adj[u].begin(); i != adj[u].end(); ++i)
             if (dist[i->getV()] < dist[u] + i->getWeight())
                dist[i->getV()] = dist[u] + i->getWeight();
        }
    }
 
    // 列印最長路徑
    for (int i = 0; i < V; i++)
        (dist[i] == NINF)? cout << "INF ": cout << dist[i] << " ";
}

[cpp] view plain copy print?
  1. // Driver program to test above functions
  2. int main()  
  3. {  
  4.     // Create a graph given in the above diagram.  Here vertex numbers are
  5.     // 0, 1, 2, 3, 4, 5 with following mappings:
  6.     // 0=r, 1=s, 2=t, 3=x, 4=y, 5=z
  7.     Graph g(6);  
  8.     g.addEdge(0, 1, 5);  
  9.     g.addEdge(0, 2, 3);  
  10.     g.addEdge(1, 3, 6);  
  11.     g.addEdge(1, 2, 2);  
  12.     g.addEdge(2, 4, 4);  
  13.     g.addEdge(2, 5, 2);  
  14.     g.addEdge(2, 3, 7);  
  15.     g.addEdge(3, 5, 1);  
  16.     g.addEdge(3, 4, -1);  
  17.     g.addEdge(4, 5, -2);  
  18.     int s = 1;  
  19.     cout << "Following are longest distances from source vertex " << s <<" \n";  
  20.     g.longestPath(s);  
  21.     return 0;  
  22. }  
// Driver program to test above functions
int main()
{
    // Create a graph given in the above diagram.  Here vertex numbers are
    // 0, 1, 2, 3, 4, 5 with following mappings:
    // 0=r, 1=s, 2=t, 3=x, 4=y, 5=z
    Graph g(6);
    g.addEdge(0, 1, 5);
    g.addEdge(0, 2, 3);
    g.addEdge(1, 3, 6);
    g.addEdge(1, 2, 2);
    g.addEdge(2, 4, 4);
    g.addEdge(2, 5, 2);
    g.addEdge(2, 3, 7);
    g.addEdge(3, 5, 1);
    g.addEdge(3, 4, -1);
    g.addEdge(4, 5, -2);
 
    int s = 1;
    cout << "Following are longest distances from source vertex " << s <<" \n";
    g.longestPath(s);
 
    return 0;
}

輸出結果: