Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- Tip sursa: oficiala (+ comentarii)
- Autor: Alexandru Petrescu
- Complexitate timp: O(N * logN)
- Complexitate memorie: O(N)
- Punctaj asteptat: 100
- **/
- #include <cstdio>
- #include <algorithm>
- FILE *fin = fopen("nespus.in", "r"), *fout = fopen("nespus.out", "w");
- #define INF 1000000000
- #define MAXN 1000000
- int w, val[2 * MAXN], urm[2 * MAXN], lista[MAXN + 1]; /// listele de adiacenta - retinerea grafului
- int viz[MAXN + 1], timp; /// fiecare bfs la "timp"-ul lui - "viz[x]" = ultimul timp (bfs) in care am dat peste nodul "x"
- int u[MAXN + 1]; /// "u[x]" = multimea din care face parte nodul "x"
- int s[2 * MAXN + 1]; /// "s[i]" = numarul de noduri din multimea cu indicele "i"; "s[0]" = numarul de multimi create
- int st[2], dr[2], q[2][MAXN + 1]; /// 2 cozi pentru bfs in paralel
- struct myc {
- int x, y, z;
- } m[MAXN]; /// muchiile din input
- inline void baga(int x, int y) { /// folosim liste de adiacenta pentru a retine graful
- w++;
- val[w] = y;
- urm[w] = lista[x];
- lista[x] = w;
- }
- inline void inserare(int x, int g) {
- q[g][dr[g]++] = x;
- if (x != -1)
- viz[x] = timp;
- }
- inline void vezi(int x, int g) { /// consideram vecinii lui "x" si ii mutam in coada "g"
- /**
- Observatie
- Muchiile gasite care duc catre noduri care nu apartin aceleiasi multimi se vor sterge
- **/
- /// nu intram in detalii, ori stii, ori nu stii sa manipulezi listele de adiacenta
- while (lista[x] != 0 && u[x] != u[val[lista[x]]])
- lista[x] = urm[lista[x]];
- if (lista[x] != 0 && viz[val[lista[x]]] != timp)
- inserare(val[lista[x]], g);
- int p = urm[lista[x]], q = lista[x];
- while (p != 0) {
- if (u[x] == u[val[p]]) {
- urm[q] = p;
- q = p;
- if (viz[val[p]] != timp)
- inserare(val[p], g);
- }
- p = urm[p];
- }
- }
- inline void bfs(int a, int b, int h) {
- /**
- - daca "a" este "-1", vizitam din "b" toate nodurile care apartin aceleiasi multimi si le fixam "h" ca multimea careia apartin mai nou
- - altfel, parcurgem in paralel subarborii lui "a" si "b" pentru a-i atrbui celui mai mic dintre ele multimea cu indicele "h"
- **/
- timp++; /// urmeaza un nou bfs
- st[0] = dr[0] = st[1] = dr[1] = 0;
- inserare(a, 0);
- inserare(b, 1);
- int g = 1;
- while (st[0] < dr[0] && st[1] < dr[1]) {
- vezi(q[g][st[g]++], g);
- if (a != -1)
- g ^= 1;
- }
- /// alegem coada din care fac parte nodurile noii multimi
- if (a == -1 || st[1] == dr[1])
- g = 1;
- else
- g = 0;
- s[h] += dr[g]; /// noua multime are "dr[g]" noduri
- if (a != -1) { /// reactualizam cardinalitatea multimii mari
- if (g == 0)
- s[u[b]] -= dr[g];
- else
- s[u[a]] -= dr[g];
- }
- for (int i = 0; i < dr[g]; i++)
- u[q[g][i]] = h; /// noua multime din care fac parte nodurile din coada este "h"
- }
- inline void scoate(int x, int y, int &best) { /// subarborele lui "x (y)" isi declara independenta fata de de cel al lui "y (x)" (in functie de care este mai mic)
- s[0]++; /// se creeaza o noua multime
- bfs(x, y, s[0]); /// reactualizam multimile dupa eliminarea teoretica muchiei intre x si y
- /// reactualizam indicele multimii cu potentialul de a fi prea mare
- if (s[u[x]] > s[best])
- best = u[x];
- if (s[u[y]] > s[best])
- best = u[y];
- }
- inline void adauga(int x, int y, int z, int k, int &ind, int &ans) {
- int multime = u[x], nod = y; /// nodurile din subarborele lui "y" urmeaza sa fie anuntate ca apartin multimii din care face parte "x"
- if (s[u[y]] > s[multime]) { /// sau invers, in caz ca subarborele lui "x" are mai putine elemente
- multime = u[y];
- nod = x;
- }
- s[u[nod]] = 0; /// multimea urmeaza sa fie goala
- bfs(-1, nod, multime); /// nodurile "u[nod]" isi cunosc noua multime din care fac parte
- /// inseram noul vecin in listele de adiacenta ale nodurilor
- baga(x, y);
- baga(y, x);
- while (s[multime] >= k) { /// daca e vreo multime care sa aiba mai mult de "k" noduri, aceea este "multime"
- ans = std::min(ans, z - m[ind].z); /// actualizam raspunsul
- scoate(m[ind].x, m[ind].y, multime); /// scoatem muchia de cost minim care se afla in padure
- ind++; /// avem o noua muchie de cost minim
- }
- }
- int main() {
- int n, k;
- fscanf(fin, "%d%d", &n, &k);
- int ind = 1; /// retinem indicele muchiei de cost minim care se afla in graf
- int ans = INF; /// initializam raspunsul cu INF, deoarece se urmareste minimizarea acestuia
- for (int i = 1; i <= n; i++) {
- u[i] = i; /// i se afla initial in multimea care ii poarta numele
- s[i] = 1; /// multimea "i" are un singur element acum
- }
- s[0] = n; /// am creat "n" multimi
- for (int i = 1; i < n; i++) {
- fscanf(fin, "%d%d%d", &m[i].x, &m[i].y, &m[i].z);
- adauga(m[i].x, m[i].y, m[i].z, k, ind, ans); /// adaugam muchiile in ordine crescatoare dupa cost
- }
- fprintf(fout, "%d\n", ans); /// obtinuram raspunsul
- fclose(fin);
- fclose(fout);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement