Cod sursa(job #1752575)

Utilizator Robert29FMI Tilica Robert Robert29 Data 4 septembrie 2016 15:41:06
Problema BFS - Parcurgere in latime Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 16.91 kb
#include <iostream>

template <class T>
class Nod
{
private:
	T _info;
	Nod* _next;
	Nod* _prev;

public:
	Nod ();
	Nod (T info);
	Nod (const Nod& other);

	T GetInfo () const;
	Nod* GetNext () const;
	Nod* GetPrev () const;

	void SetInfo (T info);
	void SetNext (Nod* next);
	void SetPrev (Nod* prev);
};

template <class T>
class ListIterator
{
private:
	Nod<T> *_current;

public:
	ListIterator ();
	ListIterator (const ListIterator& other);

	T GetInfo () const;

	ListIterator& operator++();
	ListIterator& operator--();

	ListIterator operator++(int dummyValue);
	ListIterator operator--(int dummyValue);

	bool operator==(Nod<T>* isNULL);
	bool operator!=(Nod<T>* isNULL);

	bool operator==(const ListIterator& other);
	bool operator!=(const ListIterator& other);

	void SetInfo ( Nod<T>* nod);
};


template <class T>
class List
{
private:
	Nod<T>* _first;
	Nod<T>* _last;
	unsigned int _size;

public:
	List ();
	List (const List& other);
	~List ();

	void PushBack (T info);
	void PushFront (T info);

	void PopBack ();
	void PopFront ();

	ListIterator<T> Begin ();
	ListIterator<T> End ();
};

template <class T>
class Queue
{
private:
    List<T> *_list;
    int _size;
public:
    Queue();
    ~Queue();

    int GetSize();

    void Push(T c);
    T Front();
    void Pop();
};

#include <iostream>
using namespace std;

template <class T>
Queue<T>::Queue()
{
    _list = new List<T>();
    _size = 0;
}

template <class T>
Queue<T>::~Queue()
{
    delete _list;
}

template <class T>
int Queue<T>::GetSize()
{
    return _size;
}

template <class T>
void Queue<T>::Push(T c)
{
    ++_size;
    _list->PushBack(c);
}

template <class T>
T Queue<T>::Front()
{
    return _list->Begin().GetInfo();
}

template <class T>
void Queue<T>::Pop()
{
    if(_size <= 0)
    {
        cout << "The queue is empty";
        return ;
    }
    --_size;
    _list->PopFront();
}


template <class T>
List<T>::List () :
	_first (NULL),
	_last (NULL)
{

}

/*
 * Constructor de copiere. La orice moment in care se va face o copie
 * a unui List, se va apela aceasta functie, chiar daca operatia de
 * copiere nu se face explicit de catre voi. De exemplu:
 *
 *		void f (List a);
 *
 * In functia declarata mai sus, cand se apeleaza functia cu un obiect de
 * tip List, functia va face o copie a acelui obiect si acea copie
 * se va folosi in interiorul functiei. Compilatorul va sti ca atunci cand
 * face copia sa apeleze functia voastra scrisa mai jos.
 *
 * In aceasta metoda am acces la elementele private ale parametrului
 * "other" pentru ca este de acelasi tip de data ca si clasa care
 * implementeaza constructorul (amandoua sunt de tip List).
*/

template <class T>
List<T>::List (const List& other) :
	_size (other._size)
{
	Nod<T>* iterator = other._first;

	while (iterator != NULL) {
		PushBack (iterator->GetInfo ());

		iterator = iterator->GetNext ();
	}
}

/*
 * Destructor. Se apeleaza inainte sa se dealoce memoria unui obiect de tip
 * List. Se poate apela implicit de catre compilator in cazul dealocarii unui
 * obiect local, global sau static:
 *
 *		{ List list; }
 *
 * In cazul de mai sus, se creeaza obiectul si se distruge imediat, primul
 * pas din acest proces fiind apelarea metodei de mai jos, destructorul.
 * Acesta se mai poate apela implicit si in cazul memoriei alocate dinamic,
 * dar este necesar apelul operatorului delete:
 *
 *		List *list = new List ();
 *		delete list;
 *
 * De asemenea, se poate apela si explicit. Exista situatii in care se doreste
 * acest comportament:
 *
 *		List *list = new List ();
 *		list->~List ();
 *
 * Atentie, in cazul exemplului de mai sus nu se dealoca memoria pentru
 * obiectul list, doar se apeleaza destructorul ca pe o metoda normala.
 *
 * Pentru aceasta clasa, destructorul sterge toate obiectele de tip nod ce
 * formeaza structura de lista alocata dinamic.
 */

template <class T>
List<T>::~List ()
{
	Nod<T>* iterator = _first;

	while (iterator != NULL) {
		Nod<T>* purged = iterator;
		iterator = iterator->GetNext ();

		delete purged;
	}

	_first = _last = NULL;
}

/*
 * Metoda publica ce permite adaugarea unui nou element la finalul listei.
 *
 * Interfata metodei primeste doar un obiect de tip int, dar intern
 * se aloca memorie pentru pentru un nou obiect de tip Nod si sa se
 * formeaza legaturile spre acesta.
 *
 * In acelasi timp se pastreaza in mod coerent structura interna a clasei:
 * valorile lui _first si _last.
*/

template <class T>
void List<T>::PushBack (T info)
{
	Nod<T>* nod = new Nod<T> (info);

	if (_first == NULL) {
		_first = _last = nod;

		return ;
	}

	_last->SetNext (nod); nod->SetPrev (_last);
	_last = nod;
}

/*
 * Metoda publica ce permite adaugarea unui nou element la inceputul listei.
 *
 * Interfata metodei primeste doar un obiect de tip int, dar intern
 * se aloca memorie pentru pentru un nou obiect de tip Nod si sa se
 * formeaza legaturile spre acesta.
 *
 * In acelasi timp se pastreaza in mod coerent structura interna a clasei:
 * valorile lui _first si _last.
*/

template <class T>
void List<T>::PushFront (T info)
{
	Nod<T>* nod = new Nod<T> (info);

	if (_first == NULL) {
		_first = _last = nod;

		return ;
	}

	nod->SetNext (_first); _first->SetPrev (nod);
	_first = nod;
}

/*
 * Metoda publica ce permite stergerea ultimului element al listei.
 *
 * Intern, metoda reface legaturile dintre noduri, elibereaza memoria pentru
 * elementul sters si pastreaza coerenta structura interna a clase: valorile
 * _first si _last.
*/

template <class T>
void List<T>::PopBack ()
{
	if (_last == NULL) {
		return;
	}

	Nod<T>* purged = _last;
	Nod<T>* prev = _last->GetPrev ();

	delete purged;

	if (prev == NULL) {
		_first = _last = NULL;
		return ;
	}

	prev->SetNext (NULL);
	_last = prev;
}

/*
 * Metoda publica ce permite stergerea primului element al listei.
 *
 * Intern, metoda reface legaturile dintre noduri, elibereaza memoria pentru
 * elementul sters si pastreaza coerenta structura interna a clase: valorile
 * _first si _last.
*/

template <class T>
void List<T>::PopFront ()
{
	if (_first == NULL) {
		return ;
	}

	Nod<T>* purged = _first;
	Nod<T>* next = _first->GetNext ();

	delete purged;

	if (next == NULL) {
		_first = _last = NULL;
		return ;
	}

	next->SetPrev (NULL);
	_first = next;
}

/*
 * Metoda publica ce permite obtinerea unui obiect de tip ListIterator ce
 * pastreaza informatii despre structura interna a listei. Obiectul returnat
 * este initializat cu nodul de inceput al listei.
 *
 * A se observa ca s-a apelat functia:
 *
 * 		void SetInfo (ListIterator& listIterator, Nod* nod);
 *
 * Aceasta este o functie libera ce se gaseste in definitia clasei
 * ListIterator si este folosita pentru a seta ListIteratorul pe un anumit nod
 * intern al listei. Functia este FRIEND in clasa ListIterator, special pentru
 * a avea acces la nodul curent pe care il pastreaza ListIteratorul, informatie
 * la care in mod normal nu am avea acces extern, deoarece este definita ca
 * atribut privat in clasa.
 *
 * In corpul functiei se creeaza un obiect de tip ListIterator. Acesta este
 * returnat ulterior in exteriorul apelului metodei.
*/


/*
 * Metoda publica ce permite obtinerea unui obiect de tip ListIterator ce
 * pastreaza informatii despre structura interna a listei. Obiectul returnat
 * este initializat cu nodul de final al listei.
 *
 * A se observa ca s-a apelat functia:
 *
 * 		void SetInfo (ListIterator& listIterator, Nod* nod);
 *
 * Aceasta este o functie libera ce se gaseste in definitia clasei
 * ListIterator si este folosita pentru a seta ListIteratorul pe un anumit nod
 * intern al listei. Functia este FRIEND in clasa ListIterator, special pentru
 * a avea acces la nodul curent pe care il pastreaza ListIteratorul, informatie
 * la care in mod normal nu am avea acces extern, deoarece este definita ca
 * atribut privat in clasa.
*/

template <class T>
ListIterator<T> List<T>::End ()
{
	ListIterator<T> listIterator;

	SetInfo (listIterator, _last);

	return listIterator;
}


template <class T>
ListIterator<T>::ListIterator () :
	_current (NULL)
{

}

/*
 * Constructor de copiere. La orice moment in care se va face o copie
 * a unui ListIterator, se va apela aceasta functie, chiar daca operatia de
 * copiere nu se face explicit de catre voi. De exemplu:
 *
 *		void f (ListIterator a);
 *
 * In functia declarata mai sus, cand se apeleaza functia cu un obiect de
 * tip ListIterator, functia va face o copie a acelui obiect si acea copie
 * se va folosi in interiorul functiei. Compilatorul va sti ca atunci cand
 * face copia sa apeleze functia voastra scrisa mai jos.
 *
 * In aceasta metoda am acces la elementele private ale parametrului
 * "other" pentru ca este de acelasi tip de date ca si clasa care
 * implementeaza constructorul (amandoua sunt de tip ListIterator).
*/
template <class T>
ListIterator<T>::ListIterator (const ListIterator& other) :
	_current (other._current)
{

}

/*
 * Metoda publica ce intoarce valoarea informatiei nodului curent,
 * informatie care este la origine privata
*/
template <class T>
T ListIterator<T>::GetInfo () const
{
	return _current->GetInfo ();
}

/*
 * Supraincarcare operator++ folosit pentru trecerea la urmatorul nod din lista
 * Atentie, acest operator este operator ++ prefixat. Practic el va putea fi
 * apelat prin
 *
 *      ++ iterator;
 *
 * Operatorul ++ post-fixat este implementat mai jos.
*/
template <class T>
ListIterator<T>& ListIterator<T>::operator++ ()
{
	_current = _current->GetNext ();

	return *this;
}

/*
 * Supraincarcare operator-- folosit pentru trecerea la nodul anterior din
 * lista. Atentie, acest operator este operator -- prefixat. Practic el va
 * putea fi apelat prin
 *
 *      -- iterator;
 *
 * Operatorul ++ post-fixat este implementat mai jos.
*/
template <class T>
ListIterator<T>& ListIterator<T>::operator-- ()
{
	_current = _current->GetPrev ();

	return *this;
}

/*
 * Supraincarcare operator++ folosit pentru trecerea la nodul anterior din
 * lista. Atentie, acest operator este operator ++ post-fixat. Practic el va
 * putea fi apelat prin
 *
 *      iterator ++;
 *
 * Operatorul ++ post-fixat se supraincarca primind un atribut de tip int
 * dummy, nefolosit propriu-zis, dar necesar pentru a specifica faptul ca
 * este supraincarcat in mod post-fix.
*/
template <class T>
ListIterator<T> ListIterator<T>::operator++ (int dummyValue)
{
	ListIterator temp (*this);
	++ (*this);
	return temp;
}

/*
 * Supraincarcare operator-- folosit pentru trecerea la nodul anterior din
 * lista. Atentie, acest operator este operator -- post-fixat. Practic el va
 * putea fi apelat prin
 *
 *      iterator --;
 *
 * Operatorul -- post-fixat se supraincarca primind un atribut de tip int
 * dummy, nefolosit propriu-zis, dar necesar pentru a specifica faptul ca
 * este supraincarcat in mod post-fix.
*/
template <class T>
ListIterator<T> ListIterator<T>::operator-- (int dummyValue)
{
	ListIterator temp (*this);
	-- (*this);
	return temp;
}

/*
 * Supraincarcare operator== folosit pentru compararea iteratorului cu un
 * pointer la un obiect de tip Nod. Acest operator s-a supraincarcat doar
 * pentru a putea compara un obiect de tip ListIterator cu valoarea NULL
 * pentru a avea o forma mai eleganta de a verifica daca s-a ajuns la
 * finalul (sau inceputul) listei.
*/
template <class T>
bool ListIterator<T>::operator== (Nod<T>* isNULL)
{
	return _current == isNULL;
}

/*
 * Supraincarcare operator== folosit pentru compararea iteratorului cu un
 * alt operator. Acest operator poate fi folosit la compararea a doi iteratori
 * intre ei, eventual la compararea chiar cu obiectul obtinut de la:
 *
 *      ListIterator List::Begin ();
 *
 *  sau
 *
 *      ListIterator List::End ();
*/
template <class T>
bool ListIterator<T>::operator== (const ListIterator<T>& other)
{
	return _current == other._current;
}

/*
 * Supraincarcare operator!= folosit pentru inversa compararii de egalitate,
 * implementat mai sus prin operatorul ==. Acest operator s-a supraincarcat
 * doar pentru a putea compara un obiect de tip ListIterator cu valoarea NULL
 * pentru a avea o forma mai eleganta de a verifica daca s-a ajuns la
 * finalul (sau inceputul) listei.
*/
template <class T>
bool ListIterator<T>::operator!= (Nod<T>* isNULL)
{
	return ! ((*this) == isNULL);
}

/*
 * Supraincarcare operator!= folosit pentru inversa compararii de egalitate,
 * implementat mai sus prin operatorul ==. Acest operator poate fi folosit
 * la compararea a doi iteratori intre ei, eventual la compararea chiar cu
 * obiectul obtinut de la:
 *
 *      ListIterator List::Begin ();
 *
 *  sau
 *
 *      ListIterator List::End ();
*/
template <class T>
bool ListIterator<T>::operator!= (const ListIterator<T>& other)
{
	return ! ((*this) == other);
}

/*
 * Functie externa care atribuie obiectului de tip iterator o adresa specifica
 * unui Nod. Aceasta functie a fost declarata friend in clasa ListIterator
 * pentru a avea acces la atributele private din interiorul clasei. Cum doar
 * clasa List are initial acces la nodurile interne ale listei, informatie
 * utila se poate atribui clasei ListIterator doar din interiorul clasei List.
 *
 * Aceasta functie este folosita in interiorul metodelor Begin () si End () din
 * interiorul clasei List. A se observa ca aceasta functie poate fi apelata
 * de catre oricine, atribuind un obiect de tip Nod* de oriunde, dar informatie
 * utila se poate furniza doar din interiorul clasei List, ceea ce se si
 * intampla.
 *
 * O alta metoda de a simula functionalitatea descrisa mai sus era sa atribuim
 * clasa ListIterator ca o clasa friend in interiorul clasei ListIterator, dar
 * s-a preferat aceasta solutie pentru ca lasa acces doar la functionalitatea
 * de interes pentru clasa List, nu la tot prototipul clasei ListIterator.
*/
template <class T>
void ListIterator<T>::SetInfo (Nod<T>* nod)
{
	_current = nod;
}

template <class T>
Nod<T>::Nod () :
	_info (0,0),
	_next (NULL),
	_prev (NULL)
{

}

/*
 * Constructor cu un parametru de tip int. Acesta foloseste
 * parametrul pentru initializarea informatiei.
*/
template <class T>
Nod<T>::Nod (T info) :
	_info (info),
	_next (NULL),
	_prev (NULL)
{

}

/*
 * Constructor de copiere. La orice moment in care se va face o copie
 * a unui nod, se va apela aceasta functie, chiar daca operatia de copiere
 * nu se face explicit de catre voi. De exemplu:
 *
 *		void f (nod a);
 *
 * In functia declarata mai sus, cand se apeleaza functia cu un obiect de
 * tip nod, functia va face o copie a acelui obiect si acea copie se va folosi
 * in interiorul functiei. Compilatorul va sti ca atunci cand face copia
 * sa apeleze functia voastra scrisa mai jos.
 *
 * In aceasta metoda am acces la elementele private ale parametrului
 * "other" pentru ca este de acelasi tip de date ca si clasa care
 * implementeaza constructorul (amandoua sunt de tip nod).
*/
template <class T>
Nod<T>::Nod (const Nod<T>& other) :
	_info (other._info),
	_prev (other._prev),
	_next (other._next)
{

}

/*
 * Metoda publica ce intoarce valoarea informatiei, care este la origine
 * privata
*/
template <class T>
T Nod<T>::GetInfo () const
{
	return _info;
}

/*
 * Metoda publica ce intoarce adresa spre nodul anterior, adresa ce
 * este la origine privata
*/
template <class T>
Nod<T>* Nod<T>::GetPrev () const
{
	return _prev;
}

/*
 * Metoda publica ce intoarce adresa spre urmatorul nod, adresa ce
 * este la origine privata
*/
template <class T>
Nod<T>* Nod<T>::GetNext () const
{
	return _next;
}

/*
 * Metoda publica ce modifica valoarea informatiei, care este la origine
 * privata
*/
template <class T>
void Nod<T>::SetInfo (T info)
{
	_info = info;
}

/*
 * Metoda public pentru modificarea adresei spre urmatorul nod,
 * adresa ce este la origine privata
*/
template <class T>
void Nod<T>::SetNext (Nod<T>* next)
{
	_next = next;
}

/*
 * Metoda public pentru modificarea adresei spre urmatorul nod,
 * adresa ce este la origine privata
*/
template <class T>
void Nod<T>::SetPrev (Nod<T>* prev)
{
	_prev = prev;
}


template <class T>
ListIterator<T> List<T>::Begin ()
{
	ListIterator<T> listIterator;

	listIterator.SetInfo ( _first);

	return listIterator;
}
#include <fstream>
#include <vector>
using namespace std;


ifstream fin("bfs.in");
ofstream fout("bfs.out");

#define lim 100001
vector <int> G[lim];
int path[lim];

int S,N,M;


void bfs()
{
    Queue <int> q;
    int act;
    q.Push(S);
    path[S] = 0;
    act = S;

    while(q.GetSize() > 0)
    {
        act=q.Front();
        q.Pop();

        for(int i = 0; i < G[act].size(); ++i)
        {
            int it = G[act][i];
            if(path[it]==-1)
            {
                path[it]=path[act]+1;
                q.Push(it);
            }
        }
        /*for(auto it:G[act])
            if(path[it]==-1)
            {
                path[it]=path[act]+1;
                q.Push(it);
            }*/
    }

}


int main()
{
     int i,x,y;

    fin>>N>>M>>S;

    for(i=1; i<=M; i++)
    {
        fin>>x>>y;
        G[x].push_back(y);
    }

    for(i=1; i<=N; i++)
        path[i]=-1;

    bfs();

    for(i=1; i<=N; i++)
        fout<<path[i]<<' ';

    fin.close();
    fout.close();
    return 0;
}