Undirected Graphs

COS 265 - Data Structures & Algorithms

Undirected Graphs

introduction

undirected graphs

Graph
Set of vertices connected pairwise by edges

Why study graph algorithms?

Protein-protein interaction network

[ Reference: Jeong et al Nature Review | Genetics ]

framingham heart study

[ "The Spread of Obesity in a Large Social Network over 32 Years" by Christakis and Fowler in New England Journal of Medicine, 2007 ]

the evolution of FCC lobbying coalitions

[ "The Evolution of FCC Lobbying Coalitions" by Pierre de Vries in JoSS Visualization Symposium 2010 ]

map of science clickstreams

[ http://www.plosions.org/article/info.doi/10.1371/journal.pone.0004803 ]

10 million facebook friends

[ "Visualizing Friendships" by Paul Butler ]

The Internet as mapped by the Opte Project

[ http://en.wikipedia.org/wiki/Internet ]

graph applications

graph vertex edge
communication telephone, computer fiber optic cable
circuit gate, register, processor wire
mechanical joint rod, beam, spring
financial stock, currency transactions
transportation intersection street
internet class C network connection
game board position legal move
social relationship person friendship
neural network neuron synapse
protein network protein protein-protein interaction
molecule atom bond
polygonal mesh geometry adjacency

graph terminology

Graph is made up of vertices (nodes, points) connected with edges (links, lines, arcs)

Path
sequence of vertices connected by edges
Cycle
path whose first and last vertices are the same
Vertex Degree
number of edges that connect to the vertex

Two vertices are connected if there is a path between them

graph terminology

vertex: black dot; edge: line; path: green lines (len=4); cycle: blue lines (len=5); 3 connected components; red vertex has degree 4

some graph-processing problems

problem description
s-t path Is there a path between \(s\) and \(t\)?
shortest s-t path What is the shortest path between \(s\) and \(t\)?
cycle Is there a cycle in the graph?
Euler cycle Is there a cycle that uses each edge exactly once?
Hamilton cycle Is there a cycle that uses each vertex exactly once?
connectivity Is there a path between every pair of vertices?
biconnectivity Is there a vertex whose removal disconnects the graph?
planarity Can the graph be drawn in the plane with no crossing edges?
graph isomorphism Are two graphs isomorphic?


Challenge: Which graph problems are easy? difficult? intractable?

Undirected Graphs

graph api

graph representation

Graph drawing provides intuition about the structure of the graph

Caveat: Intuition can be misleading

graph representation

Vertex representation

Anomalies: Not all graph representations can handle these

Graph API

// degree of vertex v in Graph G
public static int degree(Graph G, int V) {
    int degree = 0;
    for(int w : G.adj(v)) degree++;
    return degree;
}

graph representation: adjacency matrix

Maintain a two-dimensional \(V\)-by-\(V\) boolean array; for each edge \(v\)-\(w\) in graph: adj[v][w] = adj[v][w] = true.

    0123456789012
 0: .11..11......
 1: 1............
 2: 1............
 3: ....11.......
 4: ...1.11......
 5: 1..11........
 6: 1...1........
 7: ........1....
 8: .......1.....
 9: ..........111
10: .........1...
11: .........1..1
12: .........1.1.

Two entries for each edge

undirected graphs: quiz 1

Which is order of growth of running time of the following code fragment if the graph uses the adjacency-matrix representation, where \(V\) is the number of vertices and \(E\) is the number of edges?

// prints each edge exactly once
for(int v = 0; v < G.V(); v++)
    for(int w : G.adj(v))
        StdOut.println(v + "-" + w);

A. \(V\)

B. \(E+V\)

C. \(V^2\)

D. \(VE\)

E. I don't know

graph representation: adjacency lists

Maintain vertex-indexed array of lists

undirected graphs: quiz 2

Which is order of growth of running time of the following code fragment if the graph uses the adjacency-lists representation, where \(V\) is the number of vertices and \(E\) is the number of edges?

// prints each edge exactly once
for(int v = 0; v < G.V(); v++)
    for(int w : G.adj(v))
        StdOut.println(v + "-" + w);

A. \(V\)

B. \(E+V\)

C. \(V^2\)

D. \(VE\)

E. I don't know

graph representations

In practice, use adjacency-lists representation

graph representations


representation

space

add edge
edge between
\(v\) and \(w\)
iterate over
verts adj to \(v\)
list of edges \(E\) \(1\) \(E\) \(E\)
adjacency matrix \(V^2\) \(1^\dagger\) \(1\) \(V\)
adjacency lists \(E+V\) \(1\) \(\degree(v)\) \(\degree(v)\)

\(^\dagger\)disallows parallel edges

adjacency-list graph representation: java implementation

public class Graph {
    private final int V;
    private Bag<Integer>[] adj;     // adj lists

    public Graph(int V) {
        // create empty graph with V vertices
        this.V = V;
        adj = (Bag<Integer>[]) new Bag[V];
        for(int v = 0; v < V; v++)
            adj[v] = new Bag<Integer>();
    }

    public void addEdge(int v, int w) {
        // add edge v-w (parallel edges and self-loops allowed)
        adj[v].add(w);
        adj[w].add(v);
    }

    // iterator for vertices adjacent to v
    public Iterable<Integer> adj(int v) {
        return adj[v];
    }
}

Undirected Graphs

depth-first search

Maze exploration

Maze graph:

Graph: vertex for every intersection, edge for every passage

Goal: Explore every intersection in the maze

maze exploration: national building museum

[ http://www.smithsonianmag.com/travel/winding-history-maze-180951998/?no-ist ]

trémaux maze exploration

Algorithm:

maze exploration: easy

maze exploration: medium

maze exploration: challenge for the bored

depth-first search

Goal: systematically traverse a graph

Idea: mimic maze exploration (function-call stack acts as ball of string)

DFS (to visit a vertex v)
    Mark vertex v
    Recursively visit all unmarked verts w adj to v

Typical applications:


Design challenge: how to implement?

Depth-first search demo

To visit a vertex \(v\):

Depth-first search demo

Depth-first search demo

Depth-first search demo

Depth-first search demo

Depth-first search demo

Depth-first search demo

Depth-first search demo

Depth-first search demo

Depth-first search demo

Depth-first search demo

Depth-first search demo

Depth-first search demo

Depth-first search demo

Depth-first search demo

Depth-first search demo

Depth-first search demo

Depth-first search demo

design pattern for graph processing

Design pattern: decouple graph data type from graph processing

// print all verts connected to s
Paths paths = new Paths(G, s);
for(int v = 0; v < G.V(); v++)
    if(paths.hasPathTo(v))
        StdOut.println(v);

depth-first search: data structures

To visit a vertex \(v\)

Data structures:

depth-first search: java implementation

public class DepthFirstPaths {
    private int s;

    // marked[v] = true if v connected to s
    private boolean[] marked;

    // edgeTo[v] = previous vertex on path from s to v
    private int[] edgeTo;

    public DepthFirstPaths(Graph G, int s) {
        //  initialize data structures
        /* ...  */

        // find vertices connected to s
        dfs(G, s);
    }

    // recursive DFS does the work
    private void dfs(Graph G, int v) {
        marked[v] = true;
        for(int w : G.adj(v)) {
            if(!marked[w]) {
                edgeTo[w] = v;
                dfs(G, w);
            }
        }
    }
}

depth-first search: properties

Proposition: DFS marks all vertices connected to \(s\) in time proportional to the sum of their degrees (plus time to initialize the marked[] array).

Pf (correctness):

  • If \(w\) marked, then \(w\) connected to \(s\) (why?)
  • If \(w\) connected to \(s\), then \(w\) marked. (if \(w\) unmarked, then consider last edge on a path from \(s\) to \(w\) that goes from a marked vertex to an unmarked one)

Pf (running time): Each vertex connected to \(s\) is visited once

depth-first search: properties

Proposition: After DFS, can check if vertex \(v\) is connected to \(s\) in constant time and can find \(v\)-\(s\) path (if one exists) in time proportional to its length.

Pf. edgeTo[] is parent-link representation of a tree rooted at vert \(s\).

public boolean hasPathTo(int v) { return marked[v]; }

public Iterable<Integer> pathTo(int v) {
    if(!hasPathTo(v)) return null;
    Stack<Integer> path = new Stack<Integer>();
    for(int x = v; x != s; x = edgeTo[x])
        path.push(x);
    path.push(s);
    return path;
}

depth-first search: properties

Proposition: After DFS, can check if vertex \(v\) is connected to \(s\) in constant time and can find \(v\)-\(s\) path (if one exists) in time proportional to its length.

Pf. edgeTo[] is parent-link representation of a tree rooted at vert \(s\).

Exercise: Flood Fill

Problem: Implement flood fill (Photoshop magic wand)

Exercise: Nonrecursive DFS

Challenge: Implement DFS without recursion

One solution (see link)

Exercise: Nonrecursive DFS

Challenge: Implement DFS without recursion

Alternative solution (space proportional to \(E+V\), vertex can appear on stack more than once)

Undirected Graphs

breadth-first search

graph search

Tree traversal: Many ways to explore every vertex in binary tree

  • Inorder: ACEHMRSX
  • Preorder: SEACRHMX
  • Postorder: CAMHREXS
  • Level-order: SEXARCHM

graph search

Graph search: Many ways to explore every vertex in a graph

breadth-first search demo

Repeat until queue is empty:

breadth-first search demo

breadth-first search demo

breadth-first search demo

breadth-first search demo

breadth-first search demo

breadth-first search demo

breadth-first search demo

breadth-first search demo

breadth-first search demo

breadth-first search demo

breadth-first search demo

breadth-first search demo

breadth-first search demo

breadth-first search demo

breadth-first search demo

breadth-first search demo

breadth-first search demo

breadth-first search

Repeat until queue is empty:

  • Remove vertex \(v\) from queue
  • Add to queue all unmarked vertices adjacent to \(v\) and mark them
BFS (from source vertex s)
    Put s onto a FIFO queue, and mark s as visited
    Repeat until the queue is empty:
        Remove the least recently added vertex v
        For each unmarked neighbor of v:
            Add neighbor to the queue
            Mark neighbor

breadth-first search: java implementation

public class BreadthFirstPaths {
    private boolean[] marked;
    private int[] edgeTo;
    private int[] distTo;

    /* ... */

    private void BFS(Graph G, int s) {
        Queue<Integer> q = new Queue<Integer>();
        q.enqueue(s);   // init FIFO queue of vertices to explore
        marked[s] = true;
        distTo[s] = 0;

        while(!q.isEmpty()) {
            int v = q.dequeue();
            for(int w : G.adj(v)) {
                if(!marked[w]) {
                    // found new vertex w via edge v-w
                    q.enqueue(w);
                    marked[w] = true;
                    edgeTo[w] = v;
                    distTo[w] = distTo[v] + 1;
                }
            }
        }
    }
}

breadth-first search properties

Q. In which order does BFS examine vertices?

A. Increasing distance (number of edges) from s. Queue always consists of \(\geq 0\) vertices of distance \(k\) from \(s\), followed by \(\geq 0\) vertices of distance \(k+1\).

Proposition: In any connected graph \(G\), BFS computes shortest paths from \(s\) to all other vertices in time proportional to \(E+V\).

bfs application: routing

Fewest number of hops in a communication network

BFS application: kevin bacon numbers

http://oracleofbacon.org
Endless Games board game
SixDegrees iPhone App

Kevin Bacon graph

BFS applications: Erdös numbers

Erdös-Bacon-Sabbath

Undirected Graphs

challenges

Graph-processing challenge 1

Problem: Identify connected components

How difficult?

A. Any programmer could do it

B. Typical diligent algorithms student could do it

C. Hire an expert

D. Intractible

E. No one knows

graph-processing challenge 2

Problem: Is a graph bipartite?

How difficult?

A. Any programmer could do it

B. Typical diligent algorithms student could do it

C. Hire an expert

D. Intractible

E. No one knows

graph-processing challenge 3

Problem: Find a cycle in a graph (if one exists).

How difficult?

A. Any programmer could do it

B. Typical diligent algorithms student could do it

C. Hire an expert

D. Intractible

E. No one knows

graph-processing challenge 4

Problem: Is there a (general) cycle that uses every edge exactly once?

How difficult?

A. Any programmer could do it

B. Typical diligent algorithms student could do it

C. Hire an expert

D. Intractible

E. No one knows

graph-processing challenge 5

Problem: Is there a cycle that contains every vertex exactly once?

How difficult?

A. Any programmer could do it

B. Typical diligent algorithms student could do it

C. Hire an expert

D. Intractible

E. No one knows

graph-processing challenge 6

Problem: Are two graphs identical except for vertex names?

How difficult?

A. Any programmer could do it

B. Typical diligent algorithms student could do it

C. Hire an expert

D. Intractible

E. No one knows

graph-processing challenge 7

Problem: Can you draw a graph in the plane with no crossing edges?

How difficult?

A. Any programmer could do it

B. Typical diligent algorithms student could do it

C. Hire an expert

D. Intractible

E. No one knows

[ Try it yourself at link ]

graph traversal summary

BFS and DFS enables efficient solution of many (but not all) graph problems

graph problem BFS DFS time
s-t path X X \(E+V\)
shortest s-t path X \(E+V\)
cycle X X \(E+V\)
Euler cycle X \(E+V\)
Hamilton cycle \(\pow(2,1.657V)\)
bipartiteness (odd cycle) X X \(E + V\)
connected components X X \(E + V\)
biconnected components X \(E + V\)
planarity X \(E + V\)
graph isomorphism \(\pow(2,c\cdot\sqroot(V \log V))\)
loading...