v[ b ].push_back( a

37  Download (0)

Full text

(1)

GRAPH

(2)

COURSE OUTLINE

Basic Graph (review) Shortest Path

Minimum Spanning Tree

(3)

BASIC GRAPH

(4)

DEFINITION

G = (V, E)

(5)

MORE DEFINITIONS

weighted vs unweighted directed vs undirected

(6)

IMPLEMENTATION

(7)

UNDIRECTED GRAPH

vector< int > v[ N ] ; // an edge between a and b v[ a ].push_back( b ) ; v[ b ].push_back( a ) ;

DIRECTED GRAPH

vector< int > v[ N ] ; // an edge from a to b v[ a ].push_back( b ) ;

(8)

UNWEIGHTED GRAPH

vector< int > v[ N ] ; // an edge between a and b v[ a ].push_back( b ) ; v[ b ].push_back( a ) ;

WEIGHTED GRAPH

typedef pair< int , int > ii ; vector< ii > v[ N ] ;

// an edge between a and b with weight w v[ a ].push_back( ii( b , w ) ) ;

v[ b ].push_back( ii( a , w ) ) ; // v[ a ].emplace_back( b , w ) ; // v[ b ].emplace_back( a , w ) ;

(9)

TRAVERSING NEIGHBOR

vector< int > v[ N ] ;

// go through all vertices adjacent to a for ( int x : v[ a ] ) {

// x: a vertice directly linked to by "a"

}

typedef pair< int , int > ii ; vector< ii > v[ N ] ;

// go through all vertices adjacent to a for ( ii x : v[ a ] ) {

int b = x.first , w = x.second

// b: a vertice directly linked to by "a"

// w: weight(a, b) }

(10)

SHORTEST PATH

(11)

PATH

A path on a graph is a sequence of vertices

satisfying ( )

G = (V, E) , , , … , , ∈ V v

1

v

2

v

3

v

n−1

v

n

( , v

i

v

i+1

) ∈ E 1 ≤ i < n

(12)

WEIGHT OF A PATH

The weight of a path is the sum

, , , … , , ∈ V v

1

v

2

v

3

v

n−1

v

n

weight( , )

n−1i=1

v

i

v

i+1

(13)

SHORTEST PATH

The shortest path from to is the path with minimum weight among all paths

satisfying and

a b v

1

, , , … , v

2

v

3

v

n−1

, v

n

= a

v

1

v

n

= b

(14)

HOW TO FIND THE SHORTEST PATH

(15)

SHORTEST PATH ON UNWEIGHTED GRAPH

Breadth-First Search (BFS) Time:

O(V + E)

(16)

0-1 BFS

Implement with a deque Time:

O(V + E)

(17)

SHORTEST PATH ON WEIGHTED GRAPH

Floyd-Warshall Algorithm (All-pairs) Dijkstra's Algorithm (Single-source)

Bellman-Ford Algorithm (Single-source)

(18)

NEGATIVE EDGE

vs

NEGATIVE CYCLE

(19)

FLOYD-WARSHALL

No negative cycle

Dynamic Programming

// dis[ i ][ j ]: initialized to weight of edge(i, j) for ( int k = 1 ; k <= n ; k ++ )

for ( int i = 1 ; i <= n ; i ++ ) for ( int j = 1 ; j <= n ; j ++ )

dis[ i ][ j ] = min( dis[ i ][ j ] ,

dis[ i ][ k ] + dis[ k ][ j ] ) ; // dis[ i ][ j ]: shortest path from i to j

(20)

ADVANTAGE

easy to implement

(21)

DISADVANTAGE

Cannot handle negative cycle

O( ) V

3

(22)

DIJKSTRA'S ALGORITHM

Cannot handle negative edge Single-source

Greedy

O(E + V

2

)

(23)

ALGORITHM (INITIALIZE)

Let the source be

Maintain an unvisited vertice set (intially, ) Maintain an array , where stores the current

known shortest path from the source to vertice . (initially, )

Maintain a variable storing the vertice currently being handled.

Set and let .

s U U = V

d[] d[i]

d[i] = INF, ∀i i

p

d[s] = 0 p = s

(24)

ALGORITHM (MAIN PART)

Repeat the following procedure until is empty

For all vertices adjacent to , let it be , update with Remove from .

For all vertices in , find the vertice with smallest , and assign it to .

p U q d[q]

d[p] + weight(p, q)

p U

U d[]

p

(25)

ALGORITHM (FINALE)

now stores the shortest path from to

Time complexity: (Better for dense graph)

Can also be implemented in time with priority queue. (Better for sparse graph)

d[i] s i

O(E + V

2

)

O((E + V) log V)

(26)

SUMMARY

Why is it correct?

Why not negative edges?

(27)

IMPLEMENTATION (INITIALIZE)

bool vis[ N ] ; int vcnt = 0 ; int dis[ N ] ;

memset( vis , false , sizeof vis ) ; dis[ s ] = 0 ;

int p = s ;

(28)

IMPLEMENTATION (MAIN)

while ( true ) {

for ( ii x : v[ p ] ) if ( !vis[ x ] ) { int q = x.first , w = x.second ;

dis[ q ] = min( dis[ q ] , dis[ p ] + w ) ; }

vis[ p ] = true ; int nxtp = -1 ;

for ( int i = 0 ; i < n ; i ++ ) if ( !vis[ i ] ) {

if ( nxtp == -1 || dis[ i ] < dis[ nxtp ] ) nxtp = i ; }

if ( nxtp == -1 ) break ; else p = nxtp ;

}

(29)

BELLMAN-FORD ALGORITHM

Can handle negative cycles Single-source

O(V ⋅ E)

(30)

核心概念:放鬆(RELAX)

對一條邊 如果滿足 就更新

(u, v)

dis(u) + weight(u, v) < dis(v)

dis(v)

(31)

算法

初始化所有 為無窮大(起點設為 0)

對圖上的每一條邊放鬆一次

重複上面的步驟 次

dis(u)

V − 1

(32)

複雜度

O(V ⋅ E)

(33)

性質一

在沒負環的圖上

對任意節點 都有一條長度(經過的邊數)小於 的最

短路

v V

(34)

性質二

對於一個節點

若存在一條從 來(前一個點)的最短路

則從起點走 的最短路到 後再走 到 會是 的 一條最短路

v u

u u (u, v) v v

(35)

性質三

對於一個節點

若存在一條長度(經過的邊數)為 的最短路 則最多放鬆 輪後會得到這條最短路

v l

l

(36)

負環怎麼辦?

再做一輪?

再做

V − 1

輪?

(37)

實作

struct edge {

int u , v , w ; } ;

vector< edge > E ; int dis[ N ] ;

for ( int i = 1 ; i < n ; i ++ ) for ( edge ed : E )

dis[ ed.v ] = min( dis[ ed.v ] , dis[ ed.u ] + ed.w ) ;

Figure

Updating...

References

Related subjects :