#include <iostream>
#include <fstream>
#include <bits/stdc++.h>
using namespace std;
ifstream f("darb.in");
ofstream g("darb.out");
typedef pair<int, int> per;
const long long inf = 2000000000;
class Graf{
int numar_noduri;
int numar_muchii;
int start;
vector<vector<int>> vecini;
public:
Graf(){
numar_muchii = 0;
numar_noduri = 0;
start = 0;
};
void citire_date_orientat_start();
void citire_date_neorientat();
void citire_date_orientat();
Graf* citire_date_orientat_transpus();
void bfs(int);
void dfs(vector<bool>&,int);
void dfs_topo(vector<bool>&, int, vector<int>&);
void sortare_topologica();
int numar_componente_conexe();
int get_start();
void componente_tare_conexe(Graf&);
void sortare_topologica_ctc(vector<int>&);
void afis();
void dfs_comp(vector<bool>&, int, vector<vector<int>>&, int);
void biconex();
void dfs_biconex(vector<bool>&, int, int, vector<int>&, vector<int>&, stack<int>&, vector<vector<int>>&, int&);
void muchii_critice();
void dfs_muchii_critice(vector<bool>&,int, int, vector<int>&, vector<int>&, vector<vector<int>>&, int&);
void dijkstra();
void bellman_ford();
void prim();
void roy_floyd();
void dfs_darb(vector<bool> &, int, int , int &, int &);
void reseteaza_vizitat(vector<bool> &);
void darb();
};
int Graf::get_start(){
return start;
}
/// citiri
void Graf::citire_date_orientat(){
f>>numar_noduri;
f>>numar_muchii;
int n1,n2;
vecini.resize(numar_noduri+1);
for(int i = 0; i < numar_muchii; i++){
f>>n1>>n2;
vecini[n1].push_back(n2);
}
}
void Graf::citire_date_orientat_start(){
f>>numar_noduri;
f>>numar_muchii;
f>>start;
int n1,n2;
vecini.resize(numar_noduri+1);
for(int i = 0; i < numar_muchii; i++){
f>>n1>>n2;
vecini[n1].push_back(n2);
}
}
void Graf::citire_date_neorientat(){
f>>numar_noduri;
f>>numar_muchii;
int n1,n2;
vecini.resize(numar_noduri+1);
for(int i = 0; i < numar_muchii; i++){
f>>n1>>n2;
vecini[n1].push_back(n2);
vecini[n2].push_back(n1);
}
}
Graf* Graf::citire_date_orientat_transpus(){
f>>numar_noduri;
f>>numar_muchii;
int n1,n2;
vecini.resize(numar_noduri+1);
Graf *b = new Graf();
b->numar_muchii = this->numar_muchii;
b->numar_noduri = this->numar_noduri;
(b->vecini).resize(numar_noduri+1);
for(int i = 0; i < numar_muchii; i++){
f>>n1>>n2;
vecini[n1].push_back(n2);
(b->vecini)[n2].push_back(n1);
}
return b;
}
/// rezolvari
void Graf::bfs(int start){
vector<int> coada;
vector<int> drum_min(numar_noduri+1,-1);
vector<bool> vizitat(numar_noduri+1,false);
drum_min[start] = 0;
coada.push_back(start);
vizitat[start] = true;
int inc = 0, sf = 0;
while(inc <= sf){
for(int i = 0; i < vecini[coada[inc]].size(); i++)
if(vizitat[vecini[coada[inc]][i]] == false){
coada.push_back(vecini[coada[inc]][i]);
sf++;
drum_min[vecini[coada[inc]][i]] = drum_min[coada[inc]] + 1;
vizitat[vecini[coada[inc]][i]] = true;
}
inc++;
}
for(int i = 1; i <= numar_noduri; i++)
g<<drum_min[i]<<" ";
}
/// ----
void Graf::dfs(vector<bool> &vizitat, int start){
vizitat[start] = true;
for(int i = 0; i < vecini[start].size(); i++)
if(vizitat[vecini[start][i]] == false)
dfs(vizitat,vecini[start][i]);
}
/// ----
int Graf::numar_componente_conexe(){
vector<bool> vizitat(numar_noduri+1, false);
int cnt = 0;
for(int i = 1; i <= numar_noduri; i++)
if(vizitat[i] == false){
cnt++; dfs(vizitat,i);
}
return cnt;
}
/// -----
void Graf::dfs_topo(vector<bool> &vizitat, int start, vector<int> &stk){
vizitat[start] = true;
int i;
for(i = 0; i < vecini[start].size(); i++)
if(vizitat[vecini[start][i]] == false)
dfs_topo(vizitat, vecini[start][i], stk);
stk.push_back(start);
}
/// ----
void Graf::sortare_topologica(){
vector<bool> vizitat(numar_noduri+1,false);
vector<int> stk;
for(int i = 1; i <= numar_noduri; i++){
if(vizitat[i] == false){
dfs_topo(vizitat,i,stk);
}
}
for(int i = stk.size() - 1; i >= 0; i--)
g<<stk[i]<<" ";
}
/// ----
void Graf::sortare_topologica_ctc(vector<int> &stk){
vector<bool> vizitat(numar_noduri+1,false);
for(int i = 1; i <= numar_noduri; i++){
if(vizitat[i] == false){
dfs_topo(vizitat,i,stk);
}
}
}
/// ----
void Graf::dfs_comp(vector<bool> &vizitat, int start, vector<vector<int>> &comp, int cnt){
vizitat[start] = true;
comp[cnt].push_back(start);
for(int i = 0; i < vecini[start].size(); i++)
if(vizitat[vecini[start][i]] == false){
dfs_comp(vizitat,vecini[start][i],comp,cnt);
}
}
/// ----
void Graf::componente_tare_conexe(Graf &transpus){
vector<bool> vizitat(numar_noduri+1, false);
vector<int> stk;
int cnt = 0;
vector<vector<int>> componente;
componente.resize(numar_noduri+1);
sortare_topologica_ctc(stk);
for(int i = stk.size() - 1; i >= 0; i--)
if(vizitat[stk[i]] == false){
transpus.dfs_comp(vizitat,stk[i],componente,cnt);
cnt++;
}
g<<cnt<<'\n';
for(int i = 0; i < cnt; i++){
for(int j = 0; j < componente[i].size(); j++)
g<<componente[i][j]<<" ";
g<<'\n';
}
}
/// ----
void Graf::afis(){
cout<<numar_noduri<<" "<<numar_muchii<<'\n';
for(int i = 1; i <= numar_noduri; i++){
cout<<i<<": ";
for(int j = 0; j < vecini[i].size(); j++)
cout<<vecini[i][j]<<" ";
cout<<'\n';
}
}
/// ----
void Graf::dfs_biconex(vector<bool> &vizitat, int fiu, int tata, vector<int> &nivel, vector<int> &nma, stack<int> &stk, vector<vector<int>> &comp, int &cnt){
vizitat[fiu] = true;
stk.push(fiu);
nivel[fiu] = nivel[tata] + 1;
nma[fiu] = nivel[fiu];
int i;
for(i = 0; i < vecini[fiu].size(); i++)
if(vecini[fiu][i] != tata){
if(vizitat[vecini[fiu][i]] == true){
if(nma[fiu] > nivel[vecini[fiu][i]]) nma[fiu] = nivel[vecini[fiu][i]];
}
else{
dfs_biconex(vizitat, vecini[fiu][i], fiu, nivel, nma, stk, comp, cnt);
if(nma[fiu] > nma[vecini[fiu][i]]) nma[fiu] = nma[vecini[fiu][i]];
if(nivel[fiu] <= nma[vecini[fiu][i]]){
while(stk.top() != vecini[fiu][i]){
comp[cnt].push_back(stk.top());
stk.pop();
}
comp[cnt].push_back(vecini[fiu][i]);
stk.pop();
comp[cnt].push_back(fiu);
cnt++;
}
}
}
}
/// ----
void Graf::biconex(){
vector<vector<int>> comp;
comp.resize(numar_noduri+1);
vector<bool> vizitat(numar_noduri+1,false);
stack<int> stk;
vector<int> nivel(numar_noduri+1);
vector<int> nma(numar_noduri+1);
nivel[0] = 0;
int cnt = 0;
dfs_biconex(vizitat, 1, 0, nivel, nma, stk, comp, cnt);
g<<cnt<<'\n';
for(int i = 0; i < cnt; i++){
for(int j = 0; j < comp[i].size(); j++)
g<<comp[i][j]<<" ";
g<<'\n';
}
}
/// ----
void Graf::dfs_muchii_critice(vector<bool> &vizitat, int fiu, int tata, vector<int> &nivel, vector<int> &nma, vector<vector<int>> &comp, int &cnt){
vizitat[fiu] = true;
nivel[fiu] = nivel[tata] + 1;
nma[fiu] = nivel[fiu];
int i;
for(i = 0; i < vecini[fiu].size(); i++)
if(vecini[fiu][i] != tata){
if(vizitat[vecini[fiu][i]] == true){
if(nma[fiu] > nivel[vecini[fiu][i]]) nma[fiu] = nivel[vecini[fiu][i]];
}
else{
dfs_muchii_critice(vizitat, vecini[fiu][i], fiu, nivel, nma, comp, cnt);
if(nma[fiu] > nma[vecini[fiu][i]]) nma[fiu] = nma[vecini[fiu][i]];
if(nivel[fiu] < nma[vecini[fiu][i]]){
comp[cnt].push_back(fiu);
comp[cnt].push_back(vecini[fiu][i]);
cnt++;
}
}
}
}
/// ----
void Graf::muchii_critice(){
vector<vector<int>> comp;
comp.resize(numar_noduri+1);
vector<bool> vizitat(numar_noduri+1,false);
vector<int> nivel(numar_noduri+1);
vector<int> nma(numar_noduri+1);
nivel[0] = 0;
int cnt = 0;
dfs_muchii_critice(vizitat, 1, 0, nivel, nma, comp, cnt);
g<<cnt<<'\n';
for(int i = 0; i < cnt; i++){
for(int j = 0; j < comp[i].size(); j++)
g<<comp[i][j]<<" ";
g<<'\n';
}
}
/// ----
void Graf::dijkstra(){
priority_queue<per, vector<per>, greater<per>> pq;
f>>numar_noduri>>numar_muchii;
vector<vector<per>> vecini_cost;
vecini_cost.resize(numar_noduri+1);
for(int i = 1; i <= numar_muchii; i++){
int nod1; f>>nod1;
int nod2; f>>nod2;
int cost; f>>cost;
vecini_cost[nod1].push_back(make_pair(cost,nod2));
}
vector<int> d(numar_noduri+1,inf);
vector<bool> vizitat(numar_noduri+1,false);
vizitat.resize(numar_noduri+1);
d[1] = 0;
vizitat[1] = true;
for(int i = 0; i < vecini_cost[1].size(); i++){
d[vecini_cost[1][i].second] = vecini_cost[1][i].first;
pq.push(vecini_cost[1][i]);
}
while(pq.size() != 0){
int nod_curent = pq.top().second;
pq.pop();
if(vizitat[nod_curent] == false){
for(int i = 0; i < vecini_cost[nod_curent].size(); i++)
if(vizitat[vecini_cost[nod_curent][i].second] == false)
if(d[nod_curent] + vecini_cost[nod_curent][i].first < d[vecini_cost[nod_curent][i].second]){
d[vecini_cost[nod_curent][i].second] = d[nod_curent] + vecini_cost[nod_curent][i].first;
pq.push(make_pair(d[vecini_cost[nod_curent][i].second],vecini_cost[nod_curent][i].second));
}
}
vizitat[nod_curent] = true;
}
for(int i = 2; i <= numar_noduri; i++){
if(d[i] == inf) g<<0<<" ";
else g<<d[i]<<" ";
}
}
/// ----
void Graf::prim(){
f>>numar_noduri>>numar_muchii;
vector<vector<per>> vecini_cost;
vecini_cost.resize(numar_noduri+1);
for(int i = 1; i <= numar_muchii; i++){
int nod1; f>>nod1;
int nod2; f>>nod2;
int cost; f>>cost;
vecini_cost[nod1].push_back(make_pair(cost,nod2));
vecini_cost[nod2].push_back(make_pair(cost,nod1));
}
struct tuplu{
int a;
int cost;
int b;
tuplu(int a, int cost, int b):a(a),cost(cost),b(b){
}
};
struct selector{
bool operator()(tuplu const& t1, tuplu const& t2) {
return t1.cost > t2.cost;
}
};
priority_queue<tuplu, vector<tuplu>, selector> pq;
vector<int> part(numar_noduri+1,0);
int start = 1;
for(int i = 0; i < vecini_cost[start].size(); i++)
pq.push(tuplu(start,vecini_cost[start][i].first,vecini_cost[start][i].second));
part[1] = 1;
vector<per> rez;
int suma = 0;
while(pq.size() != 0){
int nod_curent = pq.top().b;
int start = pq.top().a;
if(part[nod_curent] == 0){
suma += pq.top().cost;
rez.push_back(make_pair(start,nod_curent));
pq.pop();
for(int i = 0; i < vecini_cost[nod_curent].size(); i++){
pq.push(tuplu(nod_curent,vecini_cost[nod_curent][i].first, vecini_cost[nod_curent][i].second));
}
part[nod_curent] = 1;
}else{
pq.pop();
}
}
g<<suma<<'\n';
g<<rez.size()<<'\n';
for(int i = 0; i < rez.size(); i++)
g<<rez[i].first<<" "<<rez[i].second<<'\n';
}
/// ----
void Graf::roy_floyd(){
int d[101][101];
f>>numar_noduri;
for(int i = 1; i <= numar_noduri; i++)
for(int j = 1; j <= numar_noduri; j++)
f>>d[i][j];
for(int k = 1; k <= numar_noduri; k++)
for(int i = 1; i <= numar_noduri; i++)
for(int j = 0; j <= numar_noduri; j++)
if(d[i][k] && d[k][j])
if(d[i][j] > d[i][k] + d[k][j] || d[i][j] == 0 and (i-j)*(j-k)*(i-k))
d[i][j] = d[i][k] + d[k][j];
for(int i = 1; i <= numar_noduri; i++){
for(int j = 1; j <= numar_noduri; j++)
g<<d[i][j]<<" ";
g<<'\n';
}
}
/// ----
void Graf::dfs_darb(vector<bool> &vizitat, int nod, int nivel, int &nivel_maxim, int &_nod)
{
vizitat[nod] = true;
if(nivel > nivel_maxim){
nivel_maxim = nivel;
_nod = nod;
}
for(int i = 0; i < vecini[nod].size(); i++){
if(!vizitat[vecini[nod][i]])
dfs_darb(vizitat,vecini[nod][i], nivel + 1, nivel_maxim, _nod);
}
}
/// ----
void Graf::reseteaza_vizitat(vector<bool> &vizitat){
for(int i = 0; i <= numar_noduri; i++)
vizitat[i] = false;
}
/// ----
void Graf::darb(){
int n1, n2;
f>>numar_noduri;
numar_muchii = numar_noduri - 1;
vecini.resize(numar_noduri+1);
for(int i = 1; i < numar_noduri; i++){
f>>n1>>n2;
vecini[n1].push_back(n2);
vecini[n2].push_back(n1);
}
vector<bool> vizitat(numar_noduri+1,false);
int _nod, nivel_maxim = 0;
dfs_darb(vizitat,1,0,nivel_maxim,_nod);
reseteaza_vizitat(vizitat);
nivel_maxim = 0;
dfs_darb(vizitat,_nod, 0,nivel_maxim,_nod);
g<<nivel_maxim + 1;
}
int main()
{
Graf a;
///a.citire_date_orientat_start();
///a.bfs(a.get_start());
///a.citire_date_neorientat();
///g<<a.numar_componente_conexe();
///a.citire_date_orientat();
///a.sortare_topologica();
///Graf *b = a.citire_date_orientat_transpus();
///a.componente_tare_conexe(*b);
///a.citire_date_neorientat();
///a.biconex();
///a.citire_date_neorientat();
///a.muchii_critice();
///a.dijkstra();
///a.prim();
///a.roy_floyd();
a.darb();
return 0;
}