Cod sursa(job #3226847)

Utilizator Remus.RughinisRemus Rughinis Remus.Rughinis Data 23 aprilie 2024 00:17:58
Problema Componente biconexe Scor 90
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5 kb
#include <iostream>
#include <queue>
#include <vector>
#include <stack>
#include <fstream>
#define MAXN 200000
#define DEBUG 0

using namespace std;

struct Edge{
  int b, cost;
};
struct EdgeFull{
  int parent, id, cost;
};

vector<vector<Edge>> v;
int r[MAXN];

vector<int> nodeComponents[MAXN];
vector<vector<int>> components;
stack<EdgeFull> edges;
int punte[MAXN];

void popComponent(int id, int parent){
  if(DEBUG){
   stack<EdgeFull> aux = edges;
    printf("demo %d %d:\n", parent + 1, id + 1);
    while(!aux.empty()){
      printf("%d %d\n", aux.top().parent + 1, aux.top().id + 1);
      aux.pop();
    }
    printf("\n");
  }

  EdgeFull lastEdge;
  components.push_back({});
  int compid = components.size() - 1;

  while(!edges.empty() && !(edges.top().parent == parent && edges.top().id == id)){
    lastEdge = edges.top();
    edges.pop(); 

    nodeComponents[lastEdge.id].push_back(compid);
    components[compid].push_back(lastEdge.id);
  }
  nodeComponents[edges.top().id].push_back(compid);
  components[compid].push_back(edges.top().id);
  nodeComponents[edges.top().parent].push_back(compid);
  components[compid].push_back(edges.top().parent);
  edges.pop();

  if(components[compid].size() == 2)
    punte[compid] = lastEdge.cost;
}

int first[MAXN], x = 1, les[MAXN];

void getComponents(int id, int parent, int cost){
  edges.push({parent, id, cost});
  first[id] = x;
  x ++;

  les[id] = first[id];
  int nrc = 0;
  for(int i = 0; i < v[id].size(); i ++){
    int other = v[id][i].b;
    if(other != parent){
      if(first[other] == 0){ // Front Edge
        getComponents(other, id, v[id][i].cost);
        nrc ++;

        if(les[other] >= first[id]){ // Daca copilul asta nu poate ajunge mai sus
          // articulation[id] = true;
          popComponent(other, id);
        }
      }
      if(les[other] < les[id])
        les[id] = les[other];
    }
  }

  // if(first[id] == 1 && nrc > 1){ // Primul vizitat trebuie sa aiba minim 2 copii
  //   articulation[id] = 1;
  // } else if(first[id] == 1)
  //   articulation[id] = 0;
}

struct Frame{
  int id, minv;
};
queue<Frame> cd; // Nodurile in care am ajuns
bool visitedComponent[MAXN], visitedNode[MAXN];
int minRoad[MAXN]; // minRoad[i] = Puntea minima dintre nodul id si nodul i
int n;

long long componentDfs(int start){
  cd.push({start, -1});
  for(int i = 0; i < components.size(); i ++)
    visitedComponent[i] = false;
  for(int i = 0; i < n; i ++)
    visitedNode[i] = false;

  while(!cd.empty()){
    int id = cd.front().id, minv = cd.front().minv;
    cd.pop();
    for(int i = 0; i < nodeComponents[id].size(); i ++){
      int comp = nodeComponents[id][i];
      int nminv = minv;
      if(!visitedComponent[comp]){ // Adaugam elementele din componenta curenta
        visitedComponent[comp] = true;

        if(components[comp].size() == 2){ // Este o punte
          if(nminv == -1 || nminv > punte[comp])
            nminv = punte[comp];
        }

        for(int j = 0; j < components[comp].size(); j ++){
          if(!visitedNode[components[comp][j]]){
            visitedNode[components[comp][j]] = true;
            cd.push({components[comp][j], nminv});
            minRoad[components[comp][j]] = nminv;
          }
        }

      }
    }
  }

  if(DEBUG)
    printf("%d:\n", start + 1);
  long long sum = 0;
  for(int i = 0; i < n; i ++){
    if(i != start){
      int val;
      if(minRoad[i] == -1)
        val = r[start];
      else
        val = min(r[start], minRoad[i]);
      sum += val;

      if(DEBUG)
        printf("%d ", val);
    } else if(DEBUG)
      printf("X ");
  }
  if(DEBUG)
    printf("\n");

  return sum;
}

int main(){
  int m;
  ifstream fin ("biconex.in");
  fin >> n >> m;
  // for(int i = 0; i < n; i ++)
  //   fin >> r[i];

  v.resize(n);
  for(int i = 0; i < m; i++){
    int a, b, c;
    fin >> a >> b;
    // fin >> c;
    a --;
    b --;

    v[a].push_back({b, c});
    v[b].push_back({a, c});
  }
  fin.close();

  getComponents(0, -1, 0);

  if(DEBUG){
    for(int i = 0; i < n; i ++)
      printf("%d ", first[i]);
    printf("\n");
    for(int i = 0; i < n; i ++)
      printf("%d ", les[i]);
    printf("\n");
    // for(int i = 0; i < n; i ++)
    //   printf("%d ", articulation[i]);
    // printf("\n\n");

    printf("Components by nodes\n");
    for(int i = 0; i < n; i ++){
      printf("%d: ", i + 1);
      for(int j = 0; j < nodeComponents[i].size(); j ++){
        printf("%d ", nodeComponents[i][j]);
      }
      printf("\n");
    }
    printf("\nNodes by components\n");
    for(int i = 0; i < components.size(); i ++){
      printf("%d: ", i);
      for(int j = 0; j < components[i].size(); j ++){
        printf("%d ", components[i][j] + 1);
      }
      printf("\n");
    }
    printf("\n");
  }

  ofstream fout ("biconex.out");
  // for(int i = 0; i < n; i ++){
  //   fout << componentDfs(i) << endl;
  // }
  fout << components.size() << "\n";
  for(int i = 0; i < components.size(); i ++){
    for(int j = 0; j < components[i].size(); j ++)
      fout << components[i][j] + 1 << " ";
    fout << "\n";
  }
  fout.close();

  return 0;
}