You are on page 1of 84

Shortest Path

Jonathan Irvin Gunawan


Google Asia Pacific
E
AT
SBTA
CVWAXTLE
IRVINGANTENGWOOY
prerequisite
tau graph
tau BFS
tau priority queue/
heap
motivation buat hari
ini
https://people.ksp.sk/~misof/ioi-syllabus/ioi-syllabus.pdf
Page 12
basically, shortest path itu
buat solve soal kayak gini
dikasih graph, tentuin path
dengan total weight terkecil
dari A ke B
yang gampang dulu ya

kalo graphnya unweighted


BFS
skip karena tadi
katanya dah tau
O(V+E) buat single
source
nah sekarang
weighted
BFS gak jalan kan?
mulai dari 0
Bellman-Ford
kita bikin array D[N]. D[x] itu berarti
shortest path “sementara” dari S ke x.

awalnya, kita assume gak ada


edgenya sama sekali, jadinya D[S] =
0, D[x] = INF untuk x ≠ S
terus kita bakal coba liat edge2nya
satu per satu, lalu kita coba “relax”
edge itu

nge-relax edge berarti ngupdate array


D dengan memanfaatkan edge tsb
misalkan edge nya adalah u->v
dengan weight w.

maka, kita coba mengupdate D[v]


dengan D[u] + w jika itu lebih optimal
void relax(int u, int v, int w){
D[v] = min(D[v], D[u] + w);
}
yaudah karena ada M
edge, algonya adalah kita
relax semua edge
for ((u, v, w) : E) {
relax(u, v, w)
}
mari kita lihat apa yang
terjadi

https://visualgo.net/en/sssp
array D[] nya jadi dist
minimum kalo cuma boleh
lewat at most satu edge
algonya bisa lu ulang K
kali supaya D[] itu jadi dist
minimum kalo boleh lewat
at most K edge
karena shortest path gak
bakal lewat lebih dari N-1
edge (kenapa?), lu bisa
ulang algonya N-1 kali
for (int i = 0; i < N - 1; ++i) {
for ((u, v, w) : E) {
relax(u, v, w)
}
}
kompleksitas?
O(VE)
gimana cara cek apakah
ada negative cycle (yang
reachable dari S)
loop satu iterasi relax lagi, cek apakah
relaxnya masi ada yang berubah

kalo ada, berarti ada negative cycle,


karena ada x yang mana S~>x lebih
optimal kalo pake >N-1 edge
tetep O(VE)
ada yang lebih cepat?
Bellman-Ford Lamborghini
Dijkstra
ide : tiap iterasi, lu greedily pilih
node dengan D terkecil, visit
node itu, relax semua edge
keluar dari node itu, dan jangan
visit node itu lagi
bool visited[N];
memset(visited, false, sizeof(visited);
for (int i = 0; i < N; ++i) {
int u = -1;
for (int j = 0; j < N; ++j) {
if (visited[j]) continue;
if (u == -1 || D[j] < D[u]) u = j;
}
for ((v, w) : adj[u]) {
relax(u, v, w);
}
}
bool visited[N];
memset(visited, false, sizeof(visited);
for (int i = 0; i < N; ++i) {
int u = -1;
for (int j = 0; j < N; ++j) {
if (visited[j]) continue;
if (u == -1 || D[j] < D[u]) u = j;
}
for ((v, w) : adj[u]) {
relax(u, v, w);
}
visited[u] = true
}
O(V^2+E)
bisa dicepetin pake
priority queue
bool visited[N];
memset(visited, false, sizeof(visited);
for (int i = 0; i < N; ++i) {
int u = -1;
for (int j = 0; j < N; ++j) {

}
if (visited[j]) continue;
if (u == -1 || D[j] < D[u]) u = j;

for ((v, w) : adj[u]) {


} cepetin ini pake
priority queue

relax(u, v, w);
}
visited[u] = true
}
typedef pair<int, int> pii;

priority_queue<pii, vector<pii>, greater<pii>> pq;


bool visited[N];

pq.push(make_pair(D[S], S));
memset(visited, false, sizeof(visited);
for (int i = 0; i < N; ++i) {
int u;
while (true) {
u = pq.top().second;
pq.pop();
if (!visited[u]) break;
}
for ((v, w) : adj[u]) {
relax(u, v, w);
pq.push(make_pair(D[v], v));
}
visited[u] = true
}
O(E lg V)
kalo mau dapetin
pathnya?
tiap node simpen “parent”nya di
mana.

untuk semua node lu cek dia terakhir


kali D nya keupdate pake edge yang
mana.
ide “greedy” dijkstra bisa
salah kalo ada negative
edge
SSSP dari 0
Floyd Warshal
Let c[i][j][k] itu shortest
path i~>j kalo cuma boleh
lewat node2 i, j, dan 1..k
Awalnya,
c[i][i][0] = 0
c[i][j][0] = cost edge i ke j
ato INF kalo gak ada edge
for k = 1, …, N

c[i][j][k] =
min(c[i][j][k-1],
c[i][k][k-1] + c[k][j][k-1])
karena c[i][j][k] ≥ c[i][j][k+1],
kita bisa pake hapus dimensi
terakhirnya, terus dia timpa2
gitu
// setup
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
C[i][j] = INF;
}
}
for (int i = 0; i < N; ++i) C[i][i] = 0;
for ((u, v, w) : E) C[u][v] = w;

// algo
for (int k = 0; k < N; ++k) {
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
C[i][j] = min(C[i][j], C[i][k] + C[k][j]);
}
}
}
lebih pendek lagi kalo punya
template/macro
#define REP(i, n) for (int (i)=0;(i)<(n);++(i))
#define MIN(a, b) a = min(a, b)

REP(k,N) REP(i,N) REP(j,N)


MIN(C[i][j], C[i][k]+C[k][j]);
O(V^3)
summary
DP/One Pass
BFS Bellman Ford Dijkstra Floyd Warshal
Bellman Ford

Runtime O(V + E) O(VE) O(E lg V) O(V^3) O(V + E)

Weighted NO YES YES YES YES

Cyclic YES YES YES YES NO

Negative
weight NO YES NO YES YES

Negative
cycle NO YES NO NO NO

All pairs NO NO NO YES NO


latihan soal deh ya
dikasi grid R*C (1≤R,C≤1k)
tiap sel bisa
# -> tembok
. -> lantai
F -> api
Y -> lu (dijamin cuma satu)
tiap detik lu bisa gerak empat arah, tapi
apinya nyebar juga. lu ga boleh kena
api.

lu mau keluar ke ujung grid, berapa


detik paling cepet (ato -1 kalo ga
mungkin)?
output = 3

output = -1
output = 2

output = 3
……
kalo ada exit yang lu bisa ke
exit itu lebih cepet dari any
api, maka lu bisa keluar
BFS dari lu supaya tau
shortest path ke semua point

BFS dari semua api langsung


barengan buat tau shortest
path minimum ke semua point
soal lagi
cari path dari A ke B yang total weightnya
minimum

tapi kalo ada yang seri, keluarin yang


banyaknya edge nya minimum

1 ≤ V, E ≤ 100k
……
tiap edge yang weightnya w
diganti jadi pair (w, 1)
soal lagi
dikasih weighted graph, tapi sekarang tiap edge
ada warnanya, putih ato hitam.

cari shortest path dari A ke B, tapi tiap kali lu


lewat dua edge konsekutif yang warnanya sama,
cost path lu nambah k

1 ≤ V, E ≤ 100k
……
lu bisa bikin “graph baru”, satu node
itu satu “state”

statenya sekarang jadi


(node sekarang lu di mana, edge
terakhir yang lu ambil warnanya apa)
terakhir
INC 2015 - Going Home
https://pandaoj.com/problem/
INC2015K
dikasi weighted directed graph, dua node spesial
S sama T.

ada Q query independen dalam bentuk x, y, z.

ditanya apakah kalo ada edge tambahan dari x


ke y bobotnya z, shortest pathnya berkurang

1 ≤ V, E, Q ≤ 100k
……
precompute untuk setiap
node u, shortest path S~>u
(to[u]) dan u~>T (from[u])
yang precompute u~>T,
caranya balik arah semua
edge, terus run SSSP dari T
terus kalo ada query x, y, z,
shortest pathnya pake edge
ini adalah to[x] + z + from[y]

cek value ini sama shortest


path asli
EOF
Q&A?

You might also like