Unique Path Graph I


Description:

Find number of total unique paths from Source to Goal.

Example:

/*
   1 ------> 4
 /  \         \
0 -> 2 -> 5 -> 6 -> 7 -> 8
 \            /
  3--------->
*/

Idea:

Directed graph, 三种方法都可以。 Backtrack有些慢,DP的方法很有效。拓展的时候,可以用parent count来记录这个node可不可以往下走。

Code:

#include <iostream>
#include <vector>
#include <climits>
#include <algorithm>
#include <functional>
#include <map>
#include <set>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <stack>
#include <queue>
#include <utility>
#include <memory>
#include <cmath>

using namespace std;

// A structure to represent a node in adjacency list
struct AdjEdge{
    AdjEdge(int d): dest(d), next(nullptr) {}
    int dest;
    AdjEdge * next;
};

struct AdjVert{
    AdjVert(): p_count(0), next(nullptr) {}
    int p_count;
    AdjEdge * next;
};

// A structure to represent a graph. A graph is an array of adjacency lists.
// Size of array will be V (number of vertices in graph)
class Graph{
public:
    Graph() = delete;
    Graph(int n): V(n), edges(n) {}

    void addEdge(int src, int dest){
        // src to dest Edge
        AdjEdge * ptr = new AdjEdge(dest);
        ptr->next=edges[src].next;
        edges[src].next=ptr;
        edges[dest].p_count++;
    }    

    const int V;
    vector<AdjVert> edges;
};


// Method 1, Backtrack

void DFS(const Graph & graph, int curr, int goal, int & count){
    if(curr==goal){
        count++;
        return;
    }

    for(AdjEdge * ptr=graph.edges[curr].next; ptr!=nullptr; ptr=ptr->next){
        DFS(graph, ptr->dest, goal, count);
    }
}

int uniquePath(const Graph & graph, int src, int goal){
    int count=0;
    DFS(graph, src, goal, count);
    return count;
}


// Method 2, DP recursion

struct VertNode{
    VertNode():p_count(0), count(0) {}
    int p_count;
    int count;
};

void searchDP(const Graph & graph, vector<VertNode>& v_node, int curr, int goal){
    if(curr==goal) return;

    for(AdjEdge * ptr=graph.edges[curr].next; ptr!=nullptr; ptr=ptr->next){
        v_node[ptr->dest].count += v_node[curr].count;
        v_node[ptr->dest].p_count--;
        if(v_node[ptr->dest].p_count==0){
            searchDP(graph, v_node, ptr->dest, goal);
        }
    }

}

int uniquePathDP(const Graph & graph, int src, int goal){

    vector<VertNode> v_node(graph.V);

    for(int i=0; i<graph.V; ++i){
        v_node[i].p_count=graph.edges[i].p_count;
    }

    v_node[src].count=1;

    searchDP(graph, v_node, src, goal);

    return v_node[goal].count;
}

// Method 3, DP iteration 
int uniquePathDPIter(const Graph & graph, int src, int goal){

    vector<VertNode> v_node(graph.V);

    for(int i=0; i<graph.V; ++i){
        v_node[i].p_count=graph.edges[i].p_count;
    }

    v_node[src].count=1;

    stack<int> v_stack;

    v_stack.push(src);

    while(!v_stack.empty()){
        int curr=v_stack.top();
        v_stack.pop();

        if(curr==goal)
            return v_node[curr].count;

        for(AdjEdge * ptr=graph.edges[curr].next; ptr!=nullptr; ptr=ptr->next){
            v_node[ptr->dest].count += v_node[curr].count;
            v_node[ptr->dest].p_count--;
            if(v_node[ptr->dest].p_count==0){
                v_stack.push(ptr->dest);
            }
        }

    }

    return 0;
}
/*
   1 ------> 4
 /  \         \
0 -> 2 -> 5 -> 6 -> 7 -> 8
 \            /
  3--------->
*/

int main(){
    // create the graph given in above fugure
    int V = 9;
    // struct Graph* graph = createGraph(V);
    Graph graph(V);
    graph.addEdge(0, 1);
    graph.addEdge(0, 2);
    graph.addEdge(0, 3);
    graph.addEdge(1, 2);
    graph.addEdge(1, 4);
    graph.addEdge(2, 5);
    graph.addEdge(3, 6);
    graph.addEdge(4, 6);
    graph.addEdge(5, 6);
    graph.addEdge(6, 7);
    graph.addEdge(7, 8);

    int src=0;
    int goal=8;
    cout<<uniquePath(graph, src, goal)<<endl;
    cout<<uniquePathDP(graph, src, goal)<<endl;
    cout<<uniquePathDPIter(graph, src, goal)<<endl;
}

results matching ""

    No results matching ""