Unique Path Graph II


Description:

Find number of total unique paths from Source to Goal.

Example:

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

Idea:

Undirected graph, 目前只有一种方法可以。 Backtrack有些慢,可以用。

DP的方法用在undirected graph上不行,因为不知道哪些是parent 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++;
        // Un-directed graph, set dest to src Edge too
        AdjEdge * ptr_rev = new AdjEdge(src);
        ptr_rev->next=edges[dest].next;
        edges[dest].next=ptr_rev;
        edges[src].p_count++;
    }   

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

// Method 1, Backtrack

void DFS(const Graph & graph, int curr, int goal, int & count, vector<bool>& vistied){
    // cout<<curr<<endl;
    if(curr==goal){
        count++;
        return;
    }

    vistied[curr]=true;

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

    vistied[curr]=false;
}

int uniquePath(const Graph & graph, int src, int goal){
    int count=0;
    vector<bool> vistied(graph.V, false);
    DFS(graph, src, goal, count, vistied);
    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, vector<bool>& vistied){
    // cout<<"->"<<curr<<endl;
    if(curr==goal) return;
    vistied[curr]=true;

    for(AdjEdge * ptr=graph.edges[curr].next; ptr!=nullptr; ptr=ptr->next){
        if(!vistied[ptr->dest]){
            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, vistied);
            // }
        }
    }

}

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;
    vector<bool> vistied(graph.V, false);

    searchDP(graph, v_node, src, goal, vistied);

    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;
    }

    vector<bool> vistied(graph.V, false);

    v_node[src].count=1;

    queue<int> v_queue;

    v_queue.push(src);

    while(!v_queue.empty()){
        int curr=v_queue.front();
        v_queue.pop();
        vistied[curr]=true;

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

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

        }

    }
    // return v_node[goal].count;
    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(6, 9);
    // graph.addEdge(7, 9);
    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 ""