Summary of Class 13. Hamiltonian path

Success is not final, failure is not fatal: it is the courage to continue that counts.

Hamiltonian path or traceable path is a path that visits each vertex of the graph exactly once.
Hamiltonian cycle (or Hamiltonian circuit) is a Hamiltonian Path such that there is an edge (in graph) from the last vertex to the first vertex of the Hamiltonian Path. 

0. Permutation and combination

set and subset:
sequence and subsequence:
https://www.mathsisfun.com/sets/sets-introduction.html
http://www.mathsisfun.com/algebra/sequences-series.html
permutation: the act of arranging all the members of a set into some sequence or order
combination: a selection of items from a collection without order

Problem: print all the combination of "abcd".  backtracking-like method and bitmask method.
Solution: recursive, bit-mask

1. brute force (STL next_permutation)

Hamiltonian cycle search : permutation of all nodes (n!)
STL: next_permutation(begin(), end()), bidirectional iterator

int adj[MAXN][MAXN];
bool hamiltonian (int n){
    int v[n];
    for (int i=0; i<n; i++)
        v[i] =i;
    do { 
        bool valid=true;
        for(int i=0; i<v.size()-1; i++) {
            if(adj[v[i]][v[i+1]] == false){
                valid=false;
                break;
            }         
        }   

        if(valid)
            return true;
    } while(next_permutation(v, v+n));
    return false;
}

2. backtracking

void hamCycleUtil(bool graph[V][V], bool visited[V], vector<int> &path, int pos, int times)
void hamCycle(bool graph[V][V])

3. DP (I think it has little value in application)

Invented by Bellman, Held, and Karp.  Good material for learning DP.

My explanation:
For every subset S of vertices check whether there is a path that visits "EACH and ONLY" the vertices in S exactly once and ends at a vertex v.  This is the state.  I use S(X) to represent the possible hamitonian path if it exists (true).

state: dp[i][j] 
    i: the ending vertex of hamitonian path
    j: the subset of all vertices.  You can use the bitmask to represent it.

initial state:
    For every subset S(x), which only includes one vertex x, it is true, because the hamitonian path starts at x and ends at x.

state transition:
    for every vertex y, if subset S does not include it has hamitonian path, which ends at vertext x, and there is a connection betweek x and y, the subset {S(x), y} will have a hamitinian path, which ends at y.

result:
    for n vertex, 2^n-1 will have all the vertices in it.  If any of them is true, there is hamitonian path

bool check_using_dp(int adj[][MAXN], int n){
    bool dp[MAXN][1<<MAXN]={0};
    for(int i=0; i<n; i++)
        dp[i][1<<i]=true;

    for(int i=0; i<(1<<n); i++){
        for(int j=0; j<n; j++)
            if(i&(1<<j)){
                for(int k=0; k<n; k++)
                    if(i&(1<<k) && adj[k][j] && k!=j && dp[k][i^(1<<j)]){
                        dp[j][i]=true;
                        break;
                    }   
            }   
    }   

    for(int i=0; i<n; i++)
        if(dp[i][(1<<n)-1])
            return true;

    return false;
}   

Question: Why DP is faster than Brute Force method in this case?

Comments

Popular posts from this blog

Summary of Class 12: Eulerian graph / Eulerian path (USACO 3.3)

Summary of Class 15 DAG -- Topological Sorting (USACO 4.4)

Summary of Class 14 Strongly Connected Components (SCC)