2020. 12. 24. 13:09γπ¨π»π« νλ‘κ·Έλλ°/μλ£κ΅¬μ‘°
ν΄λΉ κΈμ λ§μ΄κ΅¬λ―Έλμ κΈκ³Ό μν€λ°±κ³Όλ₯Ό μ°Έκ³ νλ©° μ€μ€λ‘ 곡λΆν λ΄μ©μ μ 리ν κ²μ λλ€.
Disjoint-Setμ κ°μ΄ 곡λΆν΄λ΄ μλ€!
Disjoint(μλ‘μ) Set(μ§ν©)λ λ§μ μλ‘μ λΆλΆμ§ν©λ€λ‘ λλ μ§ μμλ€μ λν μ 보λ₯Ό μ μ₯νκ³ μ‘°μνλ μλ£κ΅¬μ‘°μ λλ€.
μ΄λ¬ν νΉμ§μΌλ‘ μΈν΄ Disjoint Setμ νν°μ (partitioning) λ¬Έμ μ μ£Όλ‘ μ΄μ©λ©λλ€.
Disjoint Set μλ£κ΅¬μ‘°μλ 3κ°μ§μ μ€μν μ°μ°μ΄ μ‘΄μ¬ν©λλ€.
μλ‘μ μ§ν©μ΄λ? κ³΅ν΅ μμκ° μλ λ μ§ν©, κ΅μ§ν©μ΄ 곡μ§ν©μΈ μ§ν©μ λλ€.
μ°μ°
-
λ©μ΄ν¬ μ (MakeSet): λ§ κ·Έλλ‘ νΉμ ν μμλ§μ κ°μ§λ μ§ν©(λ€)μ λ§λλ κ²μ λλ€.
-
νμΈλ (Find): μ΄λ€ μμκ° μ£Όμ΄μ‘μ λ μ΄ μμκ° μν μ§ν©μ λ°ν ν©λλ€. μΌλ°μ μΌλ‘ ν΄λΉ μμκ° μν μ§ν©μ λννλ μμλ₯Ό λ°ν ν©λλ€.
-
μ λμ¨ (Union): λ κ°μ μ§ν©μ νλμ μ§ν©μΌλ‘ ν©μΉλ μ°μ°μ λλ€. μ΄ λ°©λ²μμ μ λμ¨ μ°μ°μ λ λν μμλ₯Ό μ λ ₯ μΈμλ‘ μ¬μ©ν©λλ€.
β» λν μμ: μ¬μ©λλ μ°μ°λ€μ 보면 νΉμ μμκ° μν μ§ν©μ λννλ λν μμκ° μ°μ λλ€. κ·Έλ¬λ λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μ μ λνλ₯Ό μ ν κΈ°μ€μ μ ν΄μΌ ν©λλ€. (μ«μλ©΄ κ°μ₯ μμ μ, λ¬Έμλ©΄ μ¬μ μ κ°μ₯ μμ λ¨μ΄ λ±)
ꡬν
λμ€μ‘°μΈνΈ μ μλ£κ΅¬μ‘°λ μΌλ°μ μΌλ‘ νΈλ¦¬ κ΅¬μ‘°λ‘ κ΅¬νλ©λλ€. νλμ μ§ν©μ νλμ νΈλ¦¬λ‘ ꡬνλλ©° νΈλ¦¬μ 루νΈλ Έλκ° ν΄λΉ μ§ν©μ λνμμκ° λλ κ²μ λλ€. μ΄λ κ²½λ‘ μμΆ(path compression)μ΄λΌλ λ°©λ²μ μ¬μ©νμ¬ μ°μ° μλλ₯Ό ν₯μμμΌ νΉμ μμμμ ν΄λΉ μμκ° μν μ§ν©μ λνμμμ λ°λ‘ μ κ·Ό ν μ μκ²ν©λλ€.
κ²½λ‘μμΆ(path compression)μ νμΈλ μ°μ°μ μν ν λλ§λ€ λ£¨νΈ λ ΈλκΉμ§ μνμ€ λ°©λ¬Έν κ° λ Έλλ€μ΄ μ§μ λ£¨νΈ λ Έλλ₯Ό κ°λ¦¬ν€λλ‘ κ°±μ ν©λλ€. μνλ μ¬κ· ν¨μλ₯Ό ν΅ν΄ μ§νλ©λλ€.
β» λ°°μ΄ parents : parents[x] = y; λΌλ λ¬Έμ₯μμ νΉμ μμ xκ° μν μ§ν©μ λν μμκ° yλΌλ κ²μ μλ―Έν©λλ€.
λ©μ΄ν¬ μ μ°μ° (MakeSet)
void make_set(int x){
parents[x] = x; // μκΈ° μμ λ§μ μμλ‘ κ°μ§λ μ§ν©μ μμ±
return;
}
νμΈλ μ°μ° (Find)
int do_find(int x) {
if(x == parents[x]) return x; //ν΄λΉ μ§ν©μ λν μμκ° μκΈ° μμ μΌ κ²½μ°
return parents[x] = do_find(parents[x]); //κ²½λ‘ μμΆ: μννλ©° κ±°μ²κ° μμλ€μ λ°λ‘ 루νΈλ‘ μ°κ²°
}
μ λμ¨ μ°μ° (Union)
void do_union(int u,int v){
u = do_find(u); //μμ uκ° μν μ§ν©μ λ£¨νΈ λ
Έλ-> uμ λ€μ λμ
.
v = do_find(v); //μμ vκ° μν μ§ν©μ λ£¨νΈ λ
Έλ-> vμ λ€μ λμ
.
if(u == v) return; // 루νΈλ
Έλκ° κ°λ€λ©΄ μ΄λ―Έ κ°μ μ§ν©μ΄λΌλ μλ―Έ μ΄λ―λ‘ λ¦¬ν΄
parents[u] = v; // κ·Έλ μ§ μλ€λ©΄ vμ 루νΈλ
Έλμ uμ λ£¨νΈ λ
Έλλ₯Ό λΆνλ€.
return;
}
μ°μ΅
κ°μ΄ λ¬Έμ λ₯Ό νλ©΄μ Disjoint-Setμ λ κ°κΉμμ Έλ΄ μλ€!
[BOJ 1976λ²: μ¬νκ°μ] https://www.acmicpc.net/problem/1976
#include<bits/stdc++.h>
using namespace std;
const int MAX=200+2;
bool impossible=false;
int N,M,parents[MAX]; // parents[x]=y μμ xκ° μν μ§ν©μ λν μμλ yμμ μλ―Έ
vector<int> plan;
int do_find(int u){
if(u==parents[u]) return u;
return parents[u]=do_find(parents[u]);
}
void do_union(int u,int v){
u=do_find(u);
v=do_find(v);
if(u==v) return;
parents[u] = v;
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(0);
cin>>N>>M;
for(int i=1;i<=N;i++) parents[i]=i; //MakeSet μ°μ°μ forλ¬ΈμΌλ‘ λμ
for(int i=1;i<=N;i++){
for(int j=1;j<=N;j++){
int connection;
cin>>connection;
if(connection){
do_union(min(i,j),max(i,j));
//μ°κ²° λμ΄μμ κ²½μ° Union μ°μ°, ν° μκ° λ£¨νΈλ
Έλκ° λκ² κΈ°μ€ μ€μ
}
}
}
while(M--){
int city;
cin>>city;
plan.push_back(city);
}
//μ¬ν κ³ν μ€ νμ¬ λμμ λ€μ λμκ° κ°μ μ§ν©μΈμ§ νμΈ
//( λν μμκ° κ°λ€ == κ°μ μ§ν©μ΄λ€ == μ°κ²°λμ΄μλ€ )
for(int i=0;i<(int)plan.size()-1;i++){
if(do_find(plan[i])!=do_find(plan[i+1])) impossible=true;
}
if(impossible) cout<<"NO\n";
else cout<<"YES\n";
return 0;
}
λΆμ‘±ν λΆλΆμ΄ μμΌλ©΄ λκΈ λΆνλλ¦¬κ² μ΅λλ€!