Pagini recente » Cod sursa (job #3003392) | Cod sursa (job #1471815) | Cod sursa (job #2260026) | Cod sursa (job #1471812) | Cod sursa (job #2944932)
#include<bits/stdc++.h>
using namespace std;
ifstream file_input("disjoint.in");
ofstream file_output("disjoint.out");
// am situatia initiala cand nodurile sunt proprii lor parinti (atatea multimi cate noduri)
// construiesc aceste seturi
// am nevoie de rangul asociat fiecarui nod astfel incat sa am un criteriu (pt reuniunea dupa rang)
// complexitate: pentru o operatie de tipul 2, O(log*N)-->log*N inversa functiei Akermann (valorile functiei cres rapid la 2 la 65536−3, inversa avand propr opusa)
// si O(1) pt tipul 1
class Graf_disjoint {
private:
int operatie, nod1, nod2;
// nr de noduri si nr de muchii
int n, m;
// trebuie sa memorez parintele (parintele imi va spune daca nodurile sunt din acelasi set)
vector<int> parinti;
// trebuie sa am rangul per nod (el imi va pune cum sa fac reuniunea)
vector<int> ranguri;
public:
void input_graf();
int find_Parent(int nod);
void join_Nodes(int u, int v);
void intersect_Nodes(int u, int v);
};
void Graf_disjoint::input_graf() {
file_input >> n >> m;
parinti.resize(n+1);
ranguri.resize(n+1);
for(int i=1 ; i <= n; i++){
// fiecare nod e propriul sau parinte
parinti[i] = i;
// initial toate nodurile au rangul 0 , sunt pe picior de egalitate
ranguri[i] =0;
}
for (int i = 1; i <= m; ++i){
file_input>> operatie>>nod1>>nod2;
if (operatie == 1) join_Nodes(nod1, nod2);
else
intersect_Nodes(nod1, nod2);
}
}
// inainte sa unesc noduri trebuie sa stabilesc parintele fiecarui nod
int Graf_disjoint::find_Parent(int nod) {
// daca nodul este propriul sau parinte il returnez
if(nod == parinti[nod]){
return nod;
}
// indiferent altfel merg pe calea stramosilor si apelez recursiv pe parintele sau pana cand
// ajung la parintele suprem
return parinti[nod] = find_Parent(parinti[nod]);
}
void Graf_disjoint::join_Nodes(int u, int v) {
// inainte de join tr sa stiu de parintele fiecarui nod
// lucrezi cu parintii mai departe din u respectiv v
int parinte_u, parinte_v;
parinte_u = find_Parent(u);
parinte_v = find_Parent(v);
// cand am relatia parinte copil nu e nevoie de update pe graduri
// fiindca e deja descoperit din conditie
if(ranguri[parinte_u] < ranguri[parinte_v]){
parinti[parinte_u] = parinte_v;
}else if (ranguri[parinte_v] < ranguri[parinte_u]){
parinti[parinte_v] = parinte_u;
} else {
// aici sunt pe picior de egalitate si imi este indiferent cum pun parintele
// am pastrat la fel cu conditia de mai sus
// aici gresc si gradul fiindca trebuie sa discriminez parintele de copil
parinti[parinte_v] = parinte_u;
ranguri[u] ++;
}
}
void Graf_disjoint::intersect_Nodes(int u, int v) {
if (parinti[u] == parinti[v]){
file_output<< "DA"<<"\n";
// trebuie sa am si partea de pattern compression (legand toate nodurile de parintele suprem)
} else if (find_Parent(v) == parinti[u]) {
file_output << "DA" << "\n";
}
else{
file_output<< "NU"<<"\n";
}
}
int main(){
Graf_disjoint my_graf;
my_graf.input_graf();
}