Guest User

Untitled

a guest
Jul 22nd, 2020
346
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.95 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. class UndirectedGraph {
  6.     // Grafo con estructura de lista de adjacencias, implementada como vector para mejorar la eficiencia de acceso/búsqueda
  7.     map<string, vector<string>> users;
  8.     int totalNodes = 0;
  9.  
  10.  
  11. public:
  12.     UndirectedGraph();
  13.     void addUser(const string& userA, const string& userB);
  14.     void find(const string& u);
  15.     void clique(vector<string> R, vector<string> P, vector<string> X);
  16.     void compact();
  17.     void follow(int n);
  18.     void showGraph();
  19. };
  20.  
  21. /**
  22.  * Constructor. No requiere parámetros. Dummy constructor.
  23.  */
  24. UndirectedGraph::UndirectedGraph() = default;
  25.  
  26. /**
  27.  * Agrega un usuario nuevo al grafo. Hace una conexión bidireccional (al descomentar la línea comentada)
  28.  * @param userA: String de usuario A conectado a usuario B
  29.  * @param userB: String de usuario B conectado a usuario A
  30.  */
  31. void UndirectedGraph::addUser(const string& userA, const string& userB) {
  32.     users[userA].push_back(userB);
  33.     // users[userB].push_back(userA);
  34.     totalNodes++;
  35. }
  36.  
  37. /**
  38.  * Muestra el grafo en pantalla. La representación es en forma de lista de adyacencia. Cada nodo está seguido de una
  39.  * flecha con todas sus conexiones
  40.  */
  41. void UndirectedGraph::showGraph() {
  42.     for (const auto& it: users){
  43.         cout << it.first << "->";
  44.         for (const auto& it2: it.second){
  45.             cout << it2 << " ";
  46.         }
  47.         cout << endl;
  48.     }
  49. }
  50.  
  51. /**
  52.  * Intenta encontrar si el usuario u existe en el grafo. Imprime en pantalla el resultado de la búsqueda. Comentado
  53.  * está un código menos eficiente pero más sencillo, el cual aprovecha la forma en que se almacenó el grafo (map)
  54.  * @param u: String de usuario a buscar en el grafo
  55.  */
  56. void UndirectedGraph::find(const string& u) {
  57.     /*
  58.     for (const auto& it: users){
  59.         if (it.first == u){
  60.             cout << "Yes" << endl;
  61.             return;
  62.         }
  63.     }
  64.     cout << "No" << endl;
  65.     */
  66.     // Cola para guardar temporalmente los nodos
  67.     queue<string> q;
  68.     // Mapa para llevar nodos y un valor de verdad de si fueron visitados
  69.     map<string, bool> visited;
  70.     // Comienza, aleatoriamente, con el "primer" nodo del grafo
  71.     q.push(users.begin()->first);
  72.     visited[users.begin()->first] = true;
  73.     // Itera hasta que la cola esté vacía
  74.     while(!q.empty()) {
  75.         // Remueve la cabeza de la cola
  76.         string currentUser = q.front();
  77.         // Revisa si el primer elemento de la cola es el buscado
  78.         if (currentUser == u) {
  79.             cout << "Yes" << endl;
  80.             return;
  81.         }
  82.         // Retira el elemento
  83.         q.pop();
  84.         // Itera en el vector de currentUser
  85.         for (auto &i : users[currentUser]) {
  86.             // Si los nodos adyacentes a currentUser no han sido visitados, se agregan para ser visitados
  87.             if (!visited[i]) {
  88.                 // Se revisa match
  89.                 if (i == u) {
  90.                     cout << "Yes" << endl;
  91.                     return;
  92.                 }
  93.                 // Se marca visitado
  94.                 visited[i] = true;
  95.                 q.push(i);
  96.             }
  97.         }
  98.     }
  99.     // No se retornó al visitar todos los nodos, implica que el elemento no se encontró
  100.     cout << "No" << endl;
  101. }
  102.  
  103. /**
  104.  * Imprime en pantalla los usuarios con más cantidad de seguidores. El orden de impresión es arbitrario (dependiente
  105.  * de cómo se agregaron) y no hay un criterio definido para conflictos (usuarios con igual cantidad de seguidores). Dada
  106.  * la construcción del algoritmo, siempre se imprimirán los últimos en ser ingresados (los que estén más profundamente
  107.  * en el grafo).
  108.  * @param n: Cantidad de usuarios con más seguidores a buscar
  109.  */
  110. void UndirectedGraph::follow(int n) {
  111.     // Si se piden más usuarios de los ingresados, retorna informando error
  112.     if (totalNodes < n){
  113.         cout << "Error: Cantidad de usuarios requeridos excede tamaño total de usuarios registrados" << endl;
  114.         return;
  115.     }
  116.     // Vector de los usuarios más seguidos
  117.     vector <string> mostFollowed;
  118.     // String temporal para almacenar persona más seguida actual
  119.     string currentMostFollowed;
  120.     // Temporal para buscar el largo máximo
  121.     int maxLength;
  122.     // Crea una copia de usuarios, para así eliminar cuando se ha agregado uno
  123.     map<string, vector<string>> copyOfUsers(users);
  124.     // Itera n veces para los usuarios requeridos
  125.      for (int i = 0; i < n; i++){
  126.          // Reinicio para buscar nuevo largo máximo
  127.          maxLength = 0;
  128.          // Busca por todos los nodos del grafo el que tenga el mayor largo
  129.          for (const auto& it: copyOfUsers){
  130.              // Si se encontró uno con mayor largo, se actualiza el largo y se almacena parcialmente el nodo
  131.              if (maxLength <= it.second.size()){
  132.                  maxLength = it.second.size();
  133.                  currentMostFollowed = it.first;
  134.              }
  135.          }
  136.          // El máximo ha sido encontrado, se agrega al vector de más seguidos
  137.          mostFollowed.push_back(currentMostFollowed);
  138.          // Se elimina de la lista, para evitar repeticiones
  139.          copyOfUsers.erase(currentMostFollowed);
  140.      }
  141.      // Impresión en pantalla
  142.      for (const auto& it: mostFollowed){
  143.          cout << it << endl;
  144.      }
  145. }
  146.  
  147. void UndirectedGraph::clique(vector<string> R, vector<string> P, vector<string> X) {
  148.     // Revisa si están vacíos, lo que implicaría que hay un clique
  149.     if (P.empty() && X.empty()){
  150.         cout << "Clique found!" << endl;
  151.         for (const auto& it: R)
  152.             cout << it << " " << endl;
  153.         return;
  154.     }
  155.     // Crea una copia de P para evitar problemas en el iterador
  156.     vector<string> pCopy(P);
  157.     for (const auto& v: pCopy){
  158.         vector<string> unionSet;
  159.         vector<string> intersectionSetPNv;
  160.         vector<string> intersectionSetXNv;
  161.         vector<string> neighborsP;
  162.         vector<string> vVector = {v};
  163.         // Obtiene los vecinos de P
  164.         for (const auto& neighbors: users[v]) neighborsP.push_back(neighbors);
  165.         // R u {v}
  166.         set_union(R.begin(), R.end(), vVector.begin(), vVector.end(), back_inserter(unionSet));
  167.         // Obtiene intersección P y N(v)
  168.         set_intersection(P.begin(), P.end(), neighborsP.begin(), neighborsP.end(), back_inserter(intersectionSetPNv));
  169.         set_intersection(X.begin(), X.end(), neighborsP.begin(), neighborsP.end(), back_inserter(intersectionSetXNv));
  170.         clique(unionSet, intersectionSetPNv, intersectionSetXNv);
  171.         vector<string> PminusV;
  172.         vector<string> XunionV;
  173.         // Obtiene P - {v} y X u {v}
  174.         set_difference(P.begin(), P.end(), vVector.begin(), vVector.end(), inserter(PminusV, PminusV.begin()));
  175.         set_union(X.begin(), X.end(), vVector.begin(), vVector.end(), back_inserter(XunionV));
  176.  
  177.         P = vector<string> (PminusV);
  178.         X = vector<string> (XunionV);
  179.     }
  180.  
  181.  
  182. }
  183.  
  184. void UndirectedGraph::compact() {
  185.     cout << "Compact" << endl;
  186. }
Advertisement
Add Comment
Please, Sign In to add comment