# PBinfo #4344 – smallworld – Rezolvare C++

Sursa: Codul lui Andrei
Limbaj: C++
Autor rezolvare: Darius

## Enunț

Teoria lumii mici spune că între oricare două persoane din lume există un șir surprinzător de scurt de persoane astfel încât între oricare două persoane consecutive din șir există o relație de prietenie. Vom numi un astfel de șir “șir de prietenie”. Lungimea unui șir de prietenie este egală cu numărul de relații de prietenie din şir. Se presupune chiar că între oricare două persoane din lume există un şir de prietenie de lungime maximum 6.
Fie N persoane identificate prin numerele de la 1 la N. Între cele N persoane există exact N-1 relații de prietenie astfel încât între oricare două persoane să existe un șir de prietenie. Distanța socială maximă pentru o persoană p este lungimea maximă a unui şir de prietenie care începe cu persoana p.

Cerința
Cunoscând numărul de persoane N precum și cele N - 1 relații de prietenie, determinaţi pentru fiecare persoană distanţa socială maximă a persoanei respective.

Date de intrare
Fișierul de intrare smallworld.in conţine pe prima linie numărul natural N şi pe următoarele N - 1 linii câte două numere p și q, care reprezintă faptul că între persoanele p și q există o relaţie de prietenie.

Date de ieșire
Fișierul de ieșire smallworld.out va conţine N linii, pe linia i fiind scrisă distanța socială maximă pentru persoana i (1 ≤ i ≤ N).

Restricții și precizări

2 ≤ N ≤ 100.000
Pentru teste în valoare de 52 de puncte, N ≤ 1000.
10 puncte se acordă pentru exemplele din enunț.

Exemplul 1:
smallworld.in

3
1 2
1 3
smallworld.out

1
2
2
Explicație
1 e la distanță maximă 1 atât de 2 cât și 3. 2 e la distanță maximă 2 de 3. 3 e la distanță maximă 2 de 2.



Exemplul 2:
smallworld.in

5
2 3
4 2
5 1
1 2
smallworld.out

2
2
3
3
3
Explicație
1 e la distanță maximă 2 de 4 și 3. 2 e la distanță maximă 2 de 5. 3 e la distanță maximă 3 de 5. 4 e la distanță maximă 3 de 5. 5 e la distanță maximă 3 de 3 și 4.

## Cod sursă C++

```cpp
/*
 Paul Diac
 solutile problema smallworld
 memorie: O(N)
 timp: O(N)
 idee: doua parcurgeri DFS/BFS din radacina aleasa nodul 1, in care calculez:
       hmax[i] = distanta maxima din subarborele i de la i pana la orice frunza
	           = 1 + maximul dintre hmax[] din fii
	   dtop[i] = distanta maxima plecand din i in sus macar o muchie si apoi eventual in jos
	           = max(dtop[parinte(i)] + 1, max(hmax[frate(i)]) - pentru orice frate/sibling)
*/
#include <stdio.h>
#include <vector>
#include <algorithm>
#define NMax 100005
using namespace std;
int N;
vector<int> p[NMax]; // p[i] = prieteni lui i
int viz[NMax], t[NMax]; // t[i] = tatal lui i
int hmax[NMax]; // distanta maxima "in jos"
int dtop[NMax]; // distanta maxima "in sus" (si apoi eventual in jos)
int phm[NMax][2]; // hm[i] = cei doi prietenii-fii ai lui i care au hmax[] cel mai mare
void DFS_hmax(int a) {
	for (int i = 0; i < p[a].size(); i++) {
		if (!viz[p[a][i]]) {
			viz[p[a][i]] = 1;
			DFS_hmax(p[a][i]);
			t[p[a][i]] = a;
		}
	}
	for (int i = 0; i < p[a].size(); i++) {
		if (hmax[a] < hmax[p[a][i]] + 1) {
			hmax[a] = hmax[p[a][i]] + 1;
		}
	}
}
void DFS_dtop(int a) {
	if (t[a]) {
		if (dtop[a] < dtop[t[a]] + 1) { dtop[a] = dtop[t[a]] + 1; }
		// evit un worst case O(N^2) - atunci cand a are foarte multi frati
		// folosesc cei doi fii ai tatalui cu hmax[] maxim pre-calculati 
		// este nevoie de doi pentru ca unul ar putea fi chiar a			
		for (int j = 0; j < 2; j++) {
			int s = phm[t[a]][j];				
			if (s != 0 && s != a && dtop[a] < hmax[s] + 2) { dtop[a] = hmax[s] + 2; }
		}
	}
	for (int i = 0; i < p[a].size(); i++) {
		if (!viz[p[a][i]]) {
			viz[p[a][i]] = 1;
			DFS_dtop(p[a][i]);
		}
	}	
}
int main() {
	freopen("smallworld.in", "r", stdin);
	freopen("smallworld.out", "w", stdout);
	scanf("%d", &N);
	int a, b, dMax;
	for (int i = 0; i < N-1; i++) {
		scanf("%d %d", &a, &b);
		p[a].push_back(b);
		p[b].push_back(a);
	}
	viz[1] = 1;
	DFS_hmax(1);
	for (int i = 1; i <= N; i++) {
		hmax[i]--;
		viz[i] = 0;
	}
	for (int i = 1; i <= N; i++) {
		if (phm[t[i]][0] == 0 || hmax[phm[t[i]][0]] < hmax[i]) {
			phm[t[i]][1] = phm[t[i]][0];
			phm[t[i]][0] = i;
		} else if (phm[t[i]][1] == 0 || hmax[phm[t[i]][1]] < hmax[i]) {
			phm[t[i]][1] = i;
		}
	}
	DFS_dtop(1);
	dMax = 0;
	for (int i = 1; i <= N; i++) {
		if (hmax[i] < dtop[i]) {
			printf("%ld\n", dtop[i]);
		} else {
			printf("%ld\n", hmax[i]);
		}
	}	
	return 0;
}
```

## Resurse

- [Pagina originală](https://codulluiandrei.ro/rezolvari/pbinfo/4344)
- [Sursa C++](https://codulluiandrei.ro/rezolvari/pbinfo/4344/cod.cpp)
- [Sursa pe GitHub](https://raw.githubusercontent.com/codulluiandrei/pbinfo/main/pbinfo-4344/main.cpp)
- [Cursuri de informatică pentru BAC](https://codulluiandrei.ro/academia/info-curs/pachet-cpp/)
