Cod sursa(job #2823217)

Utilizator IoanaLiviaPopescu15Ioana Livia IoanaLiviaPopescu15 Data 27 decembrie 2021 16:44:52
Problema Algoritmul lui Dijkstra Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 14.79 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>
#define N 100001
#define NN 101
#define Nb 50001
#define Nd 50001
#define Md 250001
#define inf 0x3f3f3f3f
#define oo 0x3f3f3f3f

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
    int contor[N];

//variabile
    int cost_total = 0;
    int diametru = 0;
    int last;

//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);
    static bool cuplaj(int x, int (&visited)[N], int (&dr)[N], int (&st)[N], vector<int> (&a)[N]);
    int find(int x);
    void connect(int x, int y);
    void kruskal();
    void Solve_Disjoint();
    void Solve_Diametru();
    void bfs(int start, queue<int>& coada);
    void Solve_RoyFloyd();
    void Solve_Roy();
    void Solve_Eulerian();
    void Solve_Cuplaj();
    void add_bellman(int x, bool (&in_q)[Nb], int (&q)[Nb+2], int cnt_q[Nb], int &dr);
    void Solve_Bellmanford();
    void Solve_Dijkstra();
};
	
 
	
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::bfs(int start, queue<int>& coada)
{
    coada.push(start);
    contor[start]=1;
    visited[start] = true;
    
    while(!coada.empty()){
        int el=coada.front();
        
        for(int i=0;i<adiacenta[el].size();i++){
            if(visited[adiacenta[el][i]]== false){
                coada.push(adiacenta[el][i]);
                contor[adiacenta[el][i]]=contor[el]+1;
                visited[adiacenta[el][i]] = true ;
	
                diametru=contor[adiacenta[el][i]];
                last=adiacenta[el][i];
	
            }
        }
        coada.pop();
    }
}

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

    queue<int> q;
    
    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);
    }
    
    bfs(1,q);

    //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
    
    for(int i = 1; i <= n; i++)
        visited[i] = false;
    
    bfs(last, q);

    fout<<diametru;
}

void Graph::Solve_Roy()
{
    ifstream in("royfloyd.in");
    ofstream out("royfloyd.out");

    int n;
    
    in>>n;
    
    int m[101][101];
    
     // practic, k = 0 case
    for(int i = 0; i < n; ++i)
    {
        for(int j = 0; j < n; ++j)
        {
            in>>m[i][j];
            
			if (i != j && !m[i][j])
					m[i][j] = oo;
        }
    }
    
    for(int k = 0; k < n; ++k)
    {
        for(int i = 0; i < n; ++i)
        {
            for(int j = 0; j < n; ++j)
            {
                if(m[i][k] + m[k][j] < m[i][j]) //vad care e drumul mai scurt dintre i->k->j , respectiv cel de pana acum
                {
                    m[i][j] = m[i][k] + m[k][j];
                }
	
            }
        }
    }
    
    for(int i = 0; i < n; ++i)
    {
        for(int j = 0; j < n; ++j)
        {
            if (m[i][j] != oo)
                 out<<m[i][j]<<' ';
            else out << 0;
        }
        out<<endl;

    }


}


void Graph::Solve_Eulerian() {

    ifstream in("ciclueuler.in");
    ofstream out("ciclueuler.out");
    
    vector<int> output; //vector output pentru raspuns

    int M, n, x, y, current, next_node, next_index; //plus N definit 100001
    in>>n>>M;
    
    bool visited_muchii[500001] = {}; //vector visited pentru muchii

    vector < pair <int, int> > evidenta[N];  //in evidenta voi retine pentru fiecare nod: (indice muchie, celalalt capat al muchiei)

    for (int i = 0; i < M; i++)
	{
	     in >> x >> y ;
	     evidenta[x].push_back(make_pair(i,y));
         evidenta[y].push_back(make_pair(i,x));
    }

    // //parcurgere
    // for(int i = 1; i <= n; ++i)
    // {
    //     out<<"Pentru nodul i = "<<i<<" avem "<<evidenta[i].size()<<endl;
    //     for(auto index : evidenta[i])
    //         out<<index.first<<' '<<i<<' '<<index.second<<endl;
    //     out<<endl;
    // }
    
    for(int i = 0; i < N; ++i)
        if(evidenta[i].size() % 2 != 0)
        {
            out<<"-1"; 
            return;
        }

    deque <int> dq;     //in dq retin nodurile pentru care trebuie sa fac parcurgeri in continuare
    dq.push_front(1);   //incep de la 1
	
    while(dq.size()!= 0){
        current = dq.front();
	
        if(evidenta[current].size() != 0)
        {
            next_index = evidenta[current][evidenta[current].size()-1].first;
	
            if(!visited_muchii[next_index])
            {
                visited_muchii[next_index] = true;
                next_node = evidenta[current][evidenta[current].size()-1].second;
                dq.push_front(next_node);
            }
            
            evidenta[current].pop_back();
	
        }
	
        else
        {
            output.push_back(current);
            dq.pop_front();
        }
    }
 
    // output.pop_back(); //scot de la capat primul nod pe care formatul de afisare nu il prevede
    // for(auto node : output) out<<node<<' ';

    for(int i = 0; i < output.size() - 1; ++i)
        out << output[i] << " ";
    
   // in.close();
   // out.close();
	
}

bool Graph::cuplaj(int x, int (&visited)[N], int (&dr)[N], int (&st)[N], vector<int> (&a)[N])
{
    if (visited[x]) return false;
    
    visited[x] = 1;
	
    for (int i = 0; i < a[x].size(); i++) 
    {
        int y = a[x][i];
	
        if (!dr[y])
        {
            dr[y] = x;
            st[x] = y;
            return true;
        }
	
    }
	
    for (int i = 0; i < a[x].size(); i++)
    {
	
        int aux = a[x][i];
        if (cuplaj(dr[aux], visited, dr, st, a)) 
        {
            st[x] = aux;
            dr[aux] = x;
            return true;
        }
    }
    
    return false;
}

void Graph::Solve_Cuplaj() {
        	
    ifstream in("cuplaj.in");
    ofstream out ("cuplaj.out");
    
    int visited[N], dr[N], st[N];
    queue < pair<int, int> > q;
    vector <int> a[N];
    int u,v,n, m, e, ans;
    bool ok = false;
    
    in >> n >> m >> e;
    
    for (int i = 0; i < e; i++)
    {
        in >> u >> v;
        a[u].push_back(v);
    }
	
    while (!ok)
    {
	
        ok = true;
	
        for (int i = 1; i <= n + m; i++) visited[i] = 0;
	
        for (int i = 1; i <= n; i++)
        {
            if (!st[i] && cuplaj(i, visited, dr, st, a))
            {
                ans++;
                ok = false;
            }
	
        }
	
    }
	
    out << ans << '\n';
	
    for (int i = 1; i <= n; i++) 
        if (st[i] > 0) out << i << ' ' << st[i] << '\n';

	
	
}

void Graph::add_bellman(int x, bool (&in_q)[Nb], int (&q)[Nb+2], int cnt_q[Nb], int &dr)
{
    if(in_q[x])  return;
	
    if(dr == Nb + 1) dr = 0;
    else dr++;
 
    in_q[x] = true;
    cnt_q[x]++;
    q[dr] = x;
}

void Graph::Solve_Bellmanford()
{
    	
    ifstream in("bellmanford.in");
    ofstream out("bellmanford.out");
    	
    const int M = 250001;
    
    int n1, n2, x, y, c, dr, n, m, st, ans[Nb], l[Nb], vf[M], next[M], v_cost[M], nr = 0, q[Nb+2], cnt_q[Nb];
    bool in_q[Nb];
    
    in>>n>>m;

	
    for(int i=1; i<=m; i++)
    {
        in>>n1>>n2>>c;
        
        vf[++nr] = n2;
        next[nr] = l[n1];
        l[n1] = nr;
        v_cost[nr] = c;
    }
	
    for(int i=1; i<=n; i++) ans[i] = inf;
	
    add_bellman(1, in_q, q, cnt_q, dr);
    
    ans[1] = 0;
	
    while(dr != st-1)
    {
        if(st == Nb + 2) st = 0;
	
        x = q[st++];
        in_q[x] = false;
	
        for(int z = l[x]; z > 0 ; z = next[z])
        {
            c = v_cost[z];
            y = vf[z];
	
            if(ans[x] < ans[y] - c)
            {
                ans[y] = ans[x] + c;
                
                add_bellman(y, in_q, q, cnt_q, dr);
	
                if(cnt_q[y] == n)
                {
                    out<<"Ciclu negativ!";
                    return;
                }
	
            }
	
        }
	
    }
	
    for(int i = 2; i <= n; i++) out<<ans[i]<<' ';
    
}

void Graph::Solve_Dijkstra()
{
    ifstream in("dijkstra.in");
    ofstream out("dijkstra.out");
    
    int n1, n2,x,y,c,vf[Md], nextt[Md],l[Nd],v_cost[Md],nr,n,m,ans[Nd], start = 1;
    priority_queue < pair<int,int> > coada;
    bool ok[Nd];
    
    in>>n>>m;
	
    for (int i = 1; i <= m ; ++i)
    {
        in>>n1>>n2>>c;
	
        vf[++nr]=n2;
        nextt[nr]=l[n1];
        l[n1]=nr;
        v_cost[nr]=c;
	
    }
    
    for (int i=1;i<=n;i++) ans[i]=inf;
    
    ans[start] = 0;
	
    coada.push(make_pair(0,start));
	
    while (!coada.empty())
    {
        while (!coada.empty() && ok[coada.top().second]) coada.pop();

        if (coada.empty()) break;
	
        x = coada.top().second;
	
        ok[x]=true;
	
        for (int z = l[x] ; z > 0 ; z = nextt[z])
        {
            c = v_cost[z];
            y = vf[z];
	
            if (ans[x] < ans[y] - c )
            {
                ans[y] = ans[x] + c ;
                
                coada.push(make_pair(-ans[y] ,y));
            }
	
        }
	
    }
	
	
    for (int i = 2 ; i <= n ; i++)
        if (ans[i] != inf) out << ans[i] << ' ';
        else out << 0 << ' ';

}

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

    //BFS
   // g.Solve_Min_Dist_BFS();

    //Sortaret
   // g.Solve_Sortaret();

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

    //disjoint
    //g.Solve_Disjoint();

    //bellmanford
    //g.Solve_Bellmanford();

    //dijkstra
    g.Solve_Dijkstra();

    /////////////////tema3
    
    //darb
    //g.Solve_Diametru();

    //royfloyd
    //g.Solve_Roy();

    ///////////////tema 4

    //eulerian
    //g.Solve_Eulerian();
 
    //cuplaj
    //g.Solve_Cuplaj();

    return 0;
}

//Surse Infoarena: