Cod sursa(job #2815072)

Utilizator IoanaLiviaPopescu15Ioana Livia IoanaLiviaPopescu15 Data 9 decembrie 2021 02:15:52
Problema Diametrul unui arbore Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 7.02 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>
#define N 100001


using namespace std;

	
class Graph {
	
public:

//structuri
    struct Muchie{
        int x;
        int y;
        int cost;
    };
//vectori 
	vector <int> adiacenta[N];
    vector <int> solution;
    vector<Muchie> muchii;
    vector<Muchie> rezultat;

//arrays
    bool visited[N];
    int T[N]; //vectorul de tati
    int S[N]; //vector de sizes

//variabile
    int cost_total = 0;
    int distanta_curenta = 1;
    int distanta_maxima = 1;
    int ultimul_nod = 0;

//functii
    void addEdge_neorientat(int h, int t);
    void addEdge_orientat(int h, int t);
	void DFS(int vf);
    void Solve_Conexe_DFS();
    void BFS_mininum_distances(int root, int n);
    void Solve_Min_Dist_BFS();
    void Solve_Sortaret();
    void Solve_APM();
    static bool compareByCost(Muchie a, Muchie b);
    int find(int x);
    void connect(int x, int y);
    void kruskal();
    void Solve_Disjoint();
    void Solve_Diametru();
    void DFS_diametru(int vf, int &distanta_curenta, int &distanta_maxima);

};
	
 
	
void Graph::addEdge_neorientat(int h,int t)
{
     adiacenta[h].push_back(t);
     adiacenta[t].push_back(h);
}

void Graph::addEdge_orientat(int h,int t)
{
     adiacenta[h].push_back(t);
}
 
	
void Graph::DFS(int vf)
{
	visited[vf] = true;
	
	for(int i = 0; i < adiacenta[vf].size(); ++i)
		if (!visited[adiacenta[vf][i]])
			DFS(adiacenta[vf][i]);
    
   solution.push_back(vf);
	
}

void Graph::Solve_Conexe_DFS()
{
    ifstream fin("dfs.in");
    ofstream fout("dfs.out");

    int n, m, n1, n2, conexe = 0;

    fin>>n>>m;

    for (int i = 1; i <= m; i++)
    {
        fin >> n1 >> n2;
        addEdge_neorientat(n1,n2);
    }

    for(int i = 1; i <= n; i++){
        if (!visited[i])
        {
           conexe += 1;
           DFS(i);
        }
    }

    fout << conexe;

    fin.close();
}


void Graph::BFS_mininum_distances(int root, int n)
{
        ofstream fout("bfs.out");

        vector<int> d(n + 1, -1);
        queue<int> q;
	
        d[root] = 0;
        q.push(root);
	
        while (!q.empty()) {
            int current = q.front();
            q.pop();
 
            for (auto &index : adiacenta[current]) {
                if (d[index] == -1)
                {
                    d[index] = d[current] + 1;
                    q.push(index);
                }
            }

        }
	
        for (int i = 1; i <= n; ++i) {
            fout << d[i] << ' ';
        }
}

void Graph::Solve_Min_Dist_BFS()
{
    ifstream fin("bfs.in");

    int n, m, n1, n2, s;

    fin>>n>>m>>s;


    for (int i = 1; i <= m; i++)
	{
        fin >> n1 >> n2;
        addEdge_orientat(n1,n2);
    }

    BFS_mininum_distances(s, n);

    fin.close();
}

void Graph::Solve_Sortaret()
{
    ifstream fin("sortaret.in");
    ofstream fout("sortaret.out");

    int n, m, n1, n2;

    fin>>n>>m;
    
    for (int i = 1; i <= m; i++)
	{
        fin >> n1 >> n2;
        addEdge_orientat(n1,n2);
    }
    
    for (int i = 1; i <= n; ++i)
    {
        if (!visited[i])
            DFS(i);
    }
	
	
    int upper_limit = solution.size() - 1;
	
    for (int i = upper_limit; i > -1; i--)
         fout << solution[i] << ' ';

    fin.close();
}

bool Graph::compareByCost(Muchie a, Muchie b)
{
    return a.cost < b.cost;
}

int Graph::find(int x){
    while (x != T[x]) {
        x = T[x];
        find(x);
    }
    return x;
}

void Graph::connect(int x, int y){
    int T_X = find(x), T_Y = find(y);
    
    if (S[T_X] >= S[T_Y]) {
        T[T_Y] = T_X;
        S[T_X] += S[T_Y];
	
    }
    else
    {
        S[T_Y] += S[T_X];
        T[T_X] = T_Y;
    }
	
}

void Graph::kruskal()
{
    for (auto muchie : muchii){
         if (find(muchie.x) != find(muchie.y)) {
            connect(muchie.x,muchie.y);
            cost_total += muchie.cost;
            rezultat.push_back({muchie.x,muchie.y,0});
        }
    }
}

void Graph::Solve_APM()
{
    ifstream fin("apm.in");
    ofstream fout("apm.out");

    int n, M, n1, n2;
    fin>>n>>M;

    Muchie m;
    
    for (int i = 0; i < M; i++)
	{
        fin>>m.x>>m.y>>m.cost;
        muchii.push_back(m);
    }
    

    sort(muchii.begin(), muchii.end(), compareByCost);
    
    for (int i=0; i<=n; i++) {
        T[i] = i;
        S[i] = 1;
    }
    
    kruskal();
	
    fout << cost_total << "\n" << rezultat.size() << "\n";
    
    for (int i = 0; i < rezultat.size(); i++)
    {
        fout<<rezultat[i].x<<' '<<rezultat[i].y<<endl;
    }

    fin.close();

}

void Graph::Solve_Disjoint()
{
    ifstream fin("disjoint.in");
    ofstream fout("disjoint.out");

    int n, m, cod, x, y;

    fin>>n>>m;

    for (int i=0; i<=n; i++) {
        T[i] = i;
        S[i] = 1;
    }

    for(int i = 0; i < m; ++i)
    {
        fin>>cod>>x>>y;

        if(cod == 1)
        {
            connect(x, y);
        }
        
        if(cod == 2)
        {
            if(find(x) == find(y))
            {
                fout<<"DA";
            }
            else
            {
                fout<<"NU";
            }

            fout<<endl;
        }
    }

    fin.close();
}

void Graph:: DFS_diametru(int vf, int &distanta_curenta, int &distanta_maxima)
{
    visited[vf] = true;
	distanta_curenta++;
	
	for(int i = 0; i < adiacenta[vf].size(); ++i)
		if (!visited[adiacenta[vf][i]])
		{
		    DFS_diametru(adiacenta[vf][i], distanta_curenta, distanta_maxima);
		}
	
	if(adiacenta[vf].size() == 1)
	{
	    if(distanta_curenta > distanta_maxima)
	    {
	       ultimul_nod = vf;
	       distanta_maxima = distanta_curenta;
	    }
	    distanta_curenta = 0;
	}
	
}

void Graph::Solve_Diametru()
{
    ifstream fin("darb.in");
    ofstream fout("darb.out");

    int n, m, n1, n2;

    fin>>n;

    m = n - 1; //nr de muchii

    for(int i = 1; i <= m; ++i)
    {
        fin>>n1>>n2;
        addEdge_neorientat(n1,n2);
    }

    //implementez solutia de 100 de puncte: 2 parcurgeri cu DFS
    //prima dintr-un nod oarecare: la mine va fi 1
    //a doua din nodul in care am ajuns

    DFS_diametru(1, distanta_curenta, distanta_maxima);
    
    //cout<<distanta_maxima<<' '<<ultimul_nod;
   
    for(int i = 1; i <= n; i++)
        visited[i] = 0;
    
    distanta_maxima = 1, distanta_curenta = 1;
    
    DFS_diametru(ultimul_nod, distanta_curenta, distanta_maxima);
    
    //cout<<distanta_maxima + 1<<' '<<ultimul_nod<<endl;
   
    fout<<distanta_maxima;
}

int main()
{
    Graph g;
    
    //tema 1: DFS
    // g.Solve_Conexe_DFS();

    //tema 1: BFS
    //g.Solve_Min_Dist_BFS();

    //tema 1: Sortaret
    //g.Solve_Sortaret();

    //tema2: Apm
    // g.Solve_APM();

    //tema2: disjoint
    //g.Solve_Disjoint();

    //tema2: darb
    g.Solve_Diametru();

    return 0;
}