Osnovna ideja je da se formiraju svi podskupovi polja matrice između kojih postoji put (oni formiraju klase ekvivalencije tzv. komponente povezanosti). Svaki put kada se uspostavi veza između neka dva polja matrice, podskupovi kojima ona pripadaju se spajaju. Provera da li postoji put između dva polja matrice svodi se onda na proveru da li ona pripadaju istom podskupu.
Putanja od vrha do dna postoji ako i samo ako postoji putanja od bilo kog polja u prvoj vrsti matrice do bilo kog polja u poslednjoj vrsti matrice. To bi dovelo do toga da u svakom koraku moramo da proveravamo sve parove elemenata iz prve i poslednje vrste. Međutim, možemo i bolje. Dodaćemo veštački početni čvor (nazovimo ga izvor) i spojićemo ga sa svim čvorovima u prvoj vrsti matrice i završni čvor (nazovimo ga ušće) koji ćemo spojiti sa svim čvorovima u poslednjoj vrsti matrice. Tada se u svakom koraku može proveriti samo da li su izvor i ušće spojeni tj. da li pripadaju istom podskupu.
Podskupove možemo čuvati pomoću strukture podataka za predstavljanje disjunktnih podskupova.
// jednostavnosti radi matricu čuvamo u nizu dimenzije n*n
// redni broj elementa (x, y) u matrici
int kod(int x, int y, int n) {
return x*n + y;
}
int main() {
// dimenzija matrice
int n;
cin >> n;
// alociramo matricu n*n tj. niz u kom čuvamo njene elemente
bool>> a(n);
vector<vector<for (int i = 0; i < n; i++)
false);
a[i].resize(n,
// dva dodatna veštačka čvora
const int izvor = n*n;
const int usce = n*n+1;
// inicijalizujemo union-find strukturu za sve elemente matrice
// (njih n*n), izvor i ušće
2);
UF_inicijalizacija(n*n +
// spajamo izvor sa svim elementima u prvoj vrsti matrice
for (int i = 0; i < n; i++)
0, i, n));
UF_unija(izvor, kod(
// spajamo sve elemente u poslednjoj vrsti matrice sa ušćem
for (int i = 0; i < n; i++)
1, i, n), usce);
UF_unija(kod(n-
// broj jedinica
int m;
cin >> m;
// korak u kom se spajaju izvor i usce
int korak = -1;
// ucitavamo i obrađujemo jednu po jednu jedinicu
for (int k = 1; k <= m; k++) {
int x, y;
cin >> x >> y;// ako je u matrici već jedinica, nema šta da se radi
if (a[x][y]) continue;
// upisujemo jedinicu u matricu
true;
a[x][y] = // povezujemo podskupove u sva četiri smera
if (x > 0 && a[x-1][y])
1, y, n));
UF_unija(kod(x, y, n), kod(x-if (x + 1 < n && a[x+1][y])
1, y, n));
UF_unija(kod(x, y, n), kod(x+if (y > 0 && a[x][y-1])
1, n));
UF_unija(kod(x, y, n), kod(x, y-if (y + 1 < n && a[x][y+1])
1, n));
UF_unija(kod(x, y, n), kod(x, y+// proveravamo da li su izvor i ušće spojeni
if (UF_pronadji(izvor) == UF_pronadji(usce)) {
korak = k;break;
}
}
cout << korak << endl;
return 0;
}
#include <iostream>
#include <vector>
using namespace std;
int> UF_roditelj;
vector<int> UF_rang;
vector<
void UF_inicijalizacija(int n) {
UF_roditelj.resize(n);
UF_rang.resize(n);for (int i = 0; i < n; i++) {
UF_roditelj[i] = i;0;
UF_rang[i] =
}
}
int UF_pronadji(int x) {
while (x != UF_roditelj[x]) {
UF_roditelj[x] = UF_roditelj[UF_roditelj[x]];
x = UF_roditelj[x];
}return x;
}
void UF_unija(int x, int y) {
int fx = UF_pronadji(x), fy = UF_pronadji(y);
if (UF_rang[fx] < UF_rang[fy])
UF_roditelj[fx] = fy;else if (UF_rang[fy] < UF_rang[fx])
UF_roditelj[fy] = fx;else {
UF_roditelj[fx] = fy;
UF_rang[fy]++;
}
}
// jednostavnosti radi matricu čuvamo u nizu dimenzije n*n
// redni broj elementa (x, y) u matrici
int kod(int x, int y, int n) {
return x*n + y;
}
int main() {
// dimenzija matrice
int n;
cin >> n;
// alociramo matricu n*n tj. niz u kom čuvamo njene elemente
bool>> a(n);
vector<vector<for (int i = 0; i < n; i++)
false);
a[i].resize(n,
// dva dodatna veštačka čvora
const int izvor = n*n;
const int usce = n*n+1;
// inicijalizujemo union-find strukturu za sve elemente matrice
// (njih n*n), izvor i ušće
2);
UF_inicijalizacija(n*n +
// spajamo izvor sa svim elementima u prvoj vrsti matrice
for (int i = 0; i < n; i++)
0, i, n));
UF_unija(izvor, kod(
// spajamo sve elemente u poslednjoj vrsti matrice sa ušćem
for (int i = 0; i < n; i++)
1, i, n), usce);
UF_unija(kod(n-
// broj jedinica
int m;
cin >> m;
// korak u kom se spajaju izvor i usce
int korak = -1;
// ucitavamo i obrađujemo jednu po jednu jedinicu
for (int k = 1; k <= m; k++) {
int x, y;
cin >> x >> y;// ako je u matrici već jedinica, nema šta da se radi
if (a[x][y]) continue;
// upisujemo jedinicu u matricu
true;
a[x][y] = // povezujemo podskupove u sva četiri smera
if (x > 0 && a[x-1][y])
1, y, n));
UF_unija(kod(x, y, n), kod(x-if (x + 1 < n && a[x+1][y])
1, y, n));
UF_unija(kod(x, y, n), kod(x+if (y > 0 && a[x][y-1])
1, n));
UF_unija(kod(x, y, n), kod(x, y-if (y + 1 < n && a[x][y+1])
1, n));
UF_unija(kod(x, y, n), kod(x, y+// proveravamo da li su izvor i ušće spojeni
if (UF_pronadji(izvor) == UF_pronadji(usce)) {
korak = k;break;
}
}
cout << korak << endl;
return 0;
}