Pagini recente » Istoria paginii planificare/sedinta-20090403 | Cod sursa (job #1462667) | Cod sursa (job #133943) | Cod sursa (job #143392) | Cod sursa (job #3182176)
#include <bits/stdc++.h>
using namespace std;
const int max_log2 = 17;
struct Edge {
int a, b;
Edge(): a(0), b(0) {}
Edge(int a, int b) : a(a), b(b) {}
};
int main() {
///algoritmul lui Reif (Random Mate).
std::ifstream fin("dfs.in");
std::ofstream fout("dfs.out");
int n, m; fin >> n >> m;
Edge *edges = new Edge[m]();
for (int i = 0; i < m; i++) {
int a, b; fin >> a >> b;
edges[i] = Edge(a-1, b-1);
}
int *parent = new int[n](), *ancestors = new int[n](), *ancestorsNext = new int[n]();
bool *orientation = new bool[n]();
std::iota(parent, parent + n, 0);
bool workLeft = true;
while (workLeft) {
workLeft = false;
for (int i = 0; i < n; i++) {
orientation[i] = rand() & 1;
///daca orientarea e 0, presupun ca nodul e copil; pentru 1, presupun ca e parinte.
///mai tarziu ma uit la un nod copil si vad daca are un vecin parinte. il unesc cu unul dintre ei.
}
///fac stramosi aici ca sa determin radacinile din padure.
std::copy(parent, parent + n, ancestors);
for (int _ = 0; _ < max_log2; _++) {
for (int i = 0; i < n; i++) {
ancestorsNext[i] = ancestors[ancestors[i]];
}
swap(ancestors, ancestorsNext);
}
///acum ancestors[i] indica radacina arborelui i din padure.
for (int i = 0; i < m; i++) {
if (ancestors[edges[i].a] != ancestors[edges[i].b]) {
///muchia mea e intre a si b. de fapt, in momentul de fata, muchia e intre bloburile lui a si b.
///eu trag muchia intre root[a] si root[b].
workLeft = true; ///inca mai exista componente ce pot fi unite. s-ar putea sa nu le pot uni pe acestea 2 acum
///pentru ca ambele radacini sa indice "child".
///vreau ca una din radacini sa fie child si cealalta parent.
if (orientation[ancestors[edges[i].a]] ^ orientation[ancestors[edges[i].b]]) {
if (!orientation[ancestors[edges[i].a]]) {
///!nu e nevoie de lock pentru scriere. daca am un nod child cu mai multi vecini parent, nu ma
///intereseaza cine reuseste sa scrie ultimul, vreau doar ca child sa indice catre cineva.
parent[ancestors[edges[i].a]] = ancestors[edges[i].b];
} else {
parent[ancestors[edges[i].b]] = ancestors[edges[i].a];
}
}
}
}
}
int *isRoot = new int[n]();
for (int i = 0; i < n; i++) {
if (ancestors[i] == i) {
isRoot[i] = 1;
}
}
int p2 = 1;
while ((p2 << 1) <= n) {
p2 <<= 1;
}
int l = p2 - 1, r = n - 1;
while (l) {
for (int i = l; i <= r; i += 2) {
isRoot[(i - 1) >> 1] += isRoot[i];
}
for (int i = l + 1; i <= r; i += 2) {
isRoot[(i - 1) >> 1] += isRoot[i];
}
r = l - 1;
l >>= 1;
}
fout << isRoot[0];
delete[] isRoot;
delete[] orientation;
delete[] ancestorsNext;
delete[] ancestors;
delete[] parent;
delete[] edges;
fin.close();
fout.close();
return 0;
}