Pagini recente » Cod sursa (job #20823) | Cod sursa (job #1895316) | Cod sursa (job #2708537) | Cod sursa (job #317783) | Cod sursa (job #2652398)
#define fisier "lazy"
#include <fstream>
std::ifstream in(fisier ".in");
std::ofstream out(fisier ".out");
#define range(i, n) for (int i = 0; i < n; i++)
#define iter(i, v) for (auto i: v)
const int
N = 200000,
M = N;
struct Arc {int b, c1, c2;};
struct Muchie {int a, b, c1, c2;};
std::ostream& operator << (std::ostream& stream, Muchie& muchie)
{return stream << muchie.a+1 << ' ' << muchie.b+1 << '\n';}
std::istream& operator >> (std::istream& stream, Muchie& muchie)
{stream >> muchie.a >> muchie.b >> muchie.c1 >> muchie.c2; muchie.a--, muchie.b--; return stream;}
int n;
#include <vector>
namespace disjunct
{
int _set[N];
void reset(int* set = _set) // O(n) // A se apela inainte de utilizare, ca de nu esti mort.
{range (i, n) set[i] = -1;}
int rad(int x, int* set = _set) // O(log n) sau O(1).
{
std::vector<int> drum;
while (set[x] >= 0)
{
drum.push_back(x);
x = set[x];
}
iter (y, drum) // Compresie de drum pentru O(1).
set[y] = x;
return x;
}
void uneste(int rad_a, int rad_b, int* set = _set) // O(1)
{
if (set[rad_a] > set[rad_b]) // Daca a are mai putine.
std::swap(rad_a, rad_b);
set[rad_a] += set[rad_b];
set[rad_b] = rad_a;
}
}
std::vector<Muchie> _muchii;
std::vector<int> muchii; // Indici.
#include <queue>
namespace apm
{
Arc tata[N];
int rank[N];
void reset() // O(n)
{range(i, n) {tata[i].b = -1; rank[i] = 0;}}
void kruskal(std::vector<int>& muchii, int* set = disjunct::_set, void (*functie)(int) = NULL, int limita = n - 1) // O(m log m)
{
iter (idx, muchii)
{
Muchie muchie = _muchii[idx];
if (!limita)
break;
int
rad_a = disjunct::rad(muchie.a, set), // O(log n)
rad_b = disjunct::rad(muchie.b, set); // O(log n)
if (rad_a != rad_b)
{
disjunct::uneste(rad_a, rad_b, set); // O(1)
functie(idx);
limita--;
}
}
}
}
#include <algorithm>
int main()
{
int m;
in >> n >> m;
_muchii.reserve(m); // Optimizare minora.
muchii.reserve(m);
while (m--)
{
Muchie muchie;
in >> muchie;
_muchii.push_back(muchie);
}
range(i, _muchii.size())
muchii.push_back(i);
std::sort(muchii.begin(), muchii.end(),
[](int a, int b) {return _muchii[a].c1 < _muchii[b].c1;});
range(j, muchii.size()) // Voi itera manual prin indici,
{ // din cauza comportamentului neasteptat al iteratorilor in sortare.
int i = j;
while (j < muchii.size() - 1 && _muchii[muchii[i]].c2 == _muchii[muchii[j+1]].c2)
j++;
std::sort(muchii.begin() + i, muchii.begin() + j+1,
[](int a, int b) {return _muchii[a].c2 > _muchii[b].c2;});
}
disjunct::reset();
apm::reset();
apm::kruskal(muchii, disjunct::_set, [](int idx) {out << idx+1 << '\n';});
}