Cod sursa(job #2822224)

Utilizator CalinCruceanu3576Cruceanu CalinCruceanu3576 Data 23 decembrie 2021 18:39:33
Problema Parcurgere DFS - componente conexe Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 9.56 kb
#include <bits/stdc++.h>
#define MAX 0x3f3f3f3f

using namespace std;

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

bool SortParam(const pair<pair<int, int>, int> &x, const pair<pair<int, int>, int> &y)
{
  return (x.second < y.second);
}

class Graf
{
private:
  int N, M, diametru, nodStart;
  int adj3[101][101];
  vector<vector<int>> adc, adc2;
  vector<int> viz, dist, sortate, parinte, rank, vizite, circuit;
  vector<pair<pair<int, int>, int>> adj;
  vector<pair<int, int>> sol;
  vector<vector<pair<int, int>>> adj2;
  vector<bool> viz2;
  
  void Dfs(int);
  void Bfs(int);
  void DfsSortare(int);
  void DfsTareConexe(int node, vector<int> &a);
  void royFloyd();
  void dfsDarb(int, int);
  void Euler();

public:
  Graf(int, int);
  void AdaugaMuchieNeorientata(int, int);
  void AdaugaMuchieOrientata(int, int);
  int CompConexe();
  void Distanta(int);
  void Sortare();
  vector<int> SortareCTC();
  void CompTareConexe();
  static bool VerifHavHak(vector<int> a);
  void adaugaMuchieAPM(int, int, int);//se inverseaza valorile pt citirea disjoint
  void Kruskall();
  void Leaga(int, int);
  int Gaseste(int);
  void Disjoint();
  void adaugaMuchieDijkstra(int, int, int);
  void Dijkstra(int);
  void BellmanFord(int);
  void adaugaMuchieRoyFloyd();
  void AfisareRoyFloyd();
  int AfisareDarb();
  void adaugaMuchieEuler(int, int, int);
  void AfiseazaEuler();
};

void Graf ::Dfs(int nod)
{
  int i, w;
  viz[nod] = 1;
  for (i = 0; i < adc[nod].size(); i++)
  {
    w = adc[nod][i];
    if (viz[w] == 0)
      Dfs(w);
  }
}

void Graf ::Bfs(int nod)
{
  int i, w, pr;
  queue<int> Q;
  for (i = 1; i <= N; i++)
    dist[i] = -1;
  dist[nod] = 0;
  Q.push(nod);
  while (!Q.empty())
  {
    pr = Q.front();
    Q.pop();
    for (i = 0; i < adc[pr].size(); i++)
    {
      w = adc[pr][i];
      if (dist[w] == -1)
      {
        dist[w] = dist[pr] + 1;
        Q.push(w);
      }
    }
  }
}

void Graf ::DfsSortare(int nod)
{
  int i, w;
  viz[nod] = 1;
  for (i = 0; i < adc[nod].size(); i++)
  {
    w = adc[nod][i];
    if (viz[w] == 0)
      DfsSortare(w);
  }
  sortate.push_back(nod);
}

void Graf ::DfsTareConexe(int nod, vector<int> &a)
{
  viz[nod] = 1;
  for (int i = 0; i < adc2[nod].size(); i++)
  {
    int w = adc2[nod][i];
    if (viz[w] == 0)
      DfsTareConexe(w, a);
  }
  a.push_back(nod);
}

void Graf ::royFloyd()
{
  int i, j, l;
  for (l = 0; l < N; l++)
    for (i = 0; i < N; i++)
      for (j = 0; j < N; j++)
        if(i != j && adj3[i][l] != INT_MAX && adj3[l][j] != INT_MAX)
          adj3[i][j] = min(adj3[i][j], (adj3[i][l] + adj3[l][j]));
}

void Graf ::dfsDarb(int x, int d)
{
  if (d > diametru)
  {
    diametru = d;
    nodStart = x;
  }
 
  viz[x] = 1;
  for (auto i : adc[x])
    if (!viz[i])
      dfsDarb(i, d + 1);
}

void Graf::Euler()
{
  int i, curr;
  stack<int> stk;
 
  for (i = 0; i < N; ++i)
    if (adj2[i].size() & 1)
    {
      fout << -1;
      return;
    }
 
  stk.push(1);
 
  while (!stk.empty())
  {
    curr = stk.top();
 
    if (adj2[curr].size())
    {
      pair<int, int> e = adj2[curr].back();
      adj2[curr].pop_back();
 
      if (!viz2[e.second])
      {
        viz2[e.second] = true;
        stk.push(e.first);
      }
    }
    else
    {
      stk.pop();
      circuit.push_back(curr);
    }
  }
}

Graf ::Graf(int n, int m)
{
  N = n;
  M = m;
  adc.resize(n + 1);
  adc2.resize(n + 1);
  viz.resize(n + 1);
  dist.resize(n + 1);
  parinte.resize(n + 1);
  rank.resize(n + 1);
  adj2.resize(n + 1);
  vizite.resize(n + 1);
  viz2.resize(m + 1);
}

void Graf ::AdaugaMuchieNeorientata(int x, int y)
{
  adc[x].push_back(y);
  adc[y].push_back(x);
}

int Graf ::CompConexe()
{
  int i, conexe;
  conexe = 0;
  for (i = 1; i <= N; i++)
    viz[i] = 0;
  for (i = 1; i <= N; i++)
    if (viz[i] == 0)
    {
      Dfs(i);
      ++conexe;
    }
  return conexe;
}

void Graf ::AdaugaMuchieOrientata(int x, int y)
{
  adc[x].push_back(y);
}

void Graf ::Distanta(int s)
{
  int i;
  Bfs(s);
  for (i = 1; i <= N; i++)
    fout << dist[i] << " ";
}

void Graf ::Sortare()
{
  int i;
  sortate.clear();
  for (i = 1; i <= N; i++)
    viz[i] = 0;
  for (i = 1; i <= N; i++)
    if (viz[i] == 0)
      Dfs(i);
  for (i = sortate.size() - 1; i >= 0; i--)
    fout << sortate[i] << " ";
}

vector<int> Graf ::SortareCTC()
{
  for (int i = 1; i <= N; i++)
    viz[i] = 0;
  for (int i = 1; i <= N; i++)
    if (viz[i] == 0)
      DfsSortare(i);
  return sortate;
}

void Graf ::CompTareConexe()
{
  vector<vector<int>> a;
  vector<int> v_sortat = SortareCTC();
  int curr, i, j;
  for (i = 0; i <= N; i++)
    viz[i] = 0;
  for (i = v_sortat.size() - 1; i >= 0; i--)
  {
    vector<int> ctc;
    curr = v_sortat[i];
    if (viz[curr])
      continue;
    DfsTareConexe(curr, ctc);
    a.push_back(ctc);
  }
  fout << a.size() << "\n";
  for (i = 0; i < a.size(); i++)
  {
    for (j = 0; j < a[i].size(); j++)
      fout << a[i][j] << " ";
    fout << "\n";
  }
}

bool Graf :: VerifHavHak(vector<int> a) {
    int x, i;
    while(1) {
        sort(a.begin(), a.end());
        if (a.back() == 0)  //daca toate elem sunt egale cu 0
            return true;
        x = a.back();
        a.pop_back(); //se sterge ultimul elem din lista
        if (x > a.size())   //lista trebuie sa contina destule valori
            return false;
        for (i = 0; i < x; i++) {
            a[i]--;
            if (a[i] < 0)      //daca elem curent devine 0 -> fals
                return false;
        }
    }
}

void Graf ::adaugaMuchieAPM(int x, int y, int w)
{
  adj.push_back(make_pair(make_pair(x, y), w));
}

int Graf ::Gaseste(int x)
{
  if (x == parinte[x])
    return x;
  return Gaseste(parinte[x]);
}
 
void Graf::Leaga(int a, int b)
{
  int x = Gaseste(a);
  int y = Gaseste(b);
 
  if (rank[x] >= rank[y])
  {
    parinte[y] = x;
    rank[x] += rank[y];
    M++;
  }
  else
  {
    parinte[x] = y;
    rank[y] += rank[x];
    M++;
  }
}
void Graf ::Kruskall()
{
  int cost = 0, i, x, y, a, b;
  M = 0;
 
  for (i = 1; i <= N; i++)
  {
    parinte[i] = i;
    rank[i] = 1;
  }
  sort(adj.begin(), adj.end(), SortParam);
  for (i = 0; i < adj.size(); i++)
  {
    x = Gaseste(adj[i].first.first);
    y = Gaseste(adj[i].first.second);
    a = adj[i].first.first;
    b = adj[i].first.second;
    if (x != y)
    {
      sol.push_back(make_pair(b, a));
      Leaga(b, a);
      cost += adj[i].second;
    }
  }
  fout << cost << '\n';
  fout << M << '\n';
  for (i = 0; i < M; i++)
    fout << sol[i].first << ' ' << sol[i].second << '\n';
}

void Graf ::Disjoint()
{
  int i, w, x, y;
  for (i = 1; i <= N; i++)
  {
    parinte[i] = i;
    rank[i] = 1;
  }
 
  for (i = 0; i < adj.size(); i++)
  {
    w = adj[i].first.first;
    x = adj[i].first.second;
    y = adj[i].second;
    if (w == 1)
      Leaga(x, y);
    else if (Gaseste(x) == Gaseste(y))
      fout << "DA\n";
    else
      fout << "NU\n";
  }
}

void Graf :: adaugaMuchieDijkstra(int x, int y, int w)
{
  adj2[x].push_back(make_pair(y, w));
}
 
void Graf ::Dijkstra(int x)
{
  int i;
  for (i = 1; i <= N; i++)
    dist[i] = MAX;
  dist[x] = 0;
  priority_queue<pair<int, int>> q;
  q.push(make_pair(0, x));
  while (!q.empty())
  {
    int nod = q.top().second;
    q.pop();
    if (viz[nod] == true)
      continue;
    else
      viz[nod] = true;
    for (auto curr : adj2[nod])
    {
      if (dist[nod] + curr.second < dist[curr.first])
      {
        dist[curr.first] = dist[nod] + curr.second;
        q.push(make_pair(-dist[curr.first], curr.first));
      }
    }
  }
  for (i = 2; i <= N; i++)
    if (dist[i] != MAX)
      fout <<dist[i]<<" ";
    else fout<<0<<" ";
}

void Graf ::BellmanFord(int x)
{
  int i;
  for (i = 1; i <= N; i++)
    dist[i] = MAX;
  dist[x] = 0;
  priority_queue<pair<int, int>> q;
  q.push(make_pair(0, x));
  while (!q.empty())
  {
    int nod = q.top().second;
    q.pop();
    vizite[nod]++;
    if (vizite[nod] == N)
      {
        fout<<"Ciclu negativ!";
        return;
      }
    for (auto curr : adj2[nod])
    {
      if (dist[nod] + curr.second < dist[curr.first])
      {
        dist[curr.first] = dist[nod] + curr.second;
        q.push(make_pair(-dist[curr.first], curr.first));
      }
    }
  }
  for (i = 2; i <= N; i++)
    if (dist[i] != MAX)
      fout <<dist[i]<<" ";
    else fout<<0<<" ";
}

void Graf ::adaugaMuchieRoyFloyd()
{
  int i, j;
  for (i = 0; i < N; i++)
  {
    for (j = 0; j < N; j++)
    {
      fin >> adj3[i][j];
      if (i != j && adj3[i][j] == 0)
        adj3[i][j] = INT_MAX;
    }
  }
}

void Graf ::AfisareRoyFloyd()
{
  int i, j;
  royFloyd();
  for (i = 0; i < N; i++)
  {
    for (j = 0; j < N; j++)
        fout << adj3[i][j] << " ";
    fout << "\n";
  }
}

int Graf ::AfisareDarb()
{
  int i;
  dfsDarb(1, 1);
  for (i = 0; i < N; i++)
    viz[i] = 0;
  diametru = 0;
  dfsDarb(nodStart, 1);
  return diametru;
}

void Graf::adaugaMuchieEuler(int x, int y, int i)
{
  adj2[x].push_back(make_pair(y, i));
  adj2[y].push_back(make_pair(x, i));
}

void Graf::AfiseazaEuler()
{
  Euler();
  for (auto i : circuit)
    fout << i << " ";
}

int main()
{
  int n, m, x, y, i;
  fin >> n >> m;
  Graf G(n, m);
  for (i = 1; i <= m; i++)
  {
    fin >> x >> y;
    G.AdaugaMuchieNeorientata(x, y);
  }
  fout << G.CompConexe();
  return 0;
}