You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

170 lines
5.1 KiB
C++

#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <stdint.h>
#include <numeric>
#include <bits/stdc++.h>
#include "aux.cpp"
using namespace std;
/**
* @brief Struct that represents an edge in the graph
*
* @param from: the starting node of the edge
* @param to: the ending node of the edge
* @param weight: the weight of the edge
*
*/
struct Edge {
string from, to;
int weight;
// void print() {
// cout << from << " --> " << to << " w: " << weight << endl;
// }
};
/**
* @brief Function that compares two edges based on their weight
*
* @param e1: the first edge
* @param e2: the second edge
* @return true if the weight of e1 is greater than the weight of e2, false otherwise
*/
bool compareEdge(Edge e1, Edge e2) {
return (e1.weight > e2.weight);
}
/**
* @brief Class that represents an undirected weighted graph
*
* @param AdjList: the adjacency list of the graph
*
* @details The class provides methods to add edges to the graph, to check if a combination of edges is valid and to find a solution to the problem
*
*/
class UndirectedWeightedGraph {
private:
void addWeightedEdge(string from, string to, int weight) {
for (Edge& edge : AdjList[from]) {
if (to == edge.to) {
edge.weight += weight;
return;
}
}
Edge newEdge;
newEdge.from = from;
newEdge.to = to;
newEdge.weight = weight;
AdjList[from].push_back(newEdge);
}
public:
unordered_map<string, vector<Edge>> AdjList;
void addEdge(string node1, string node2) {
addWeightedEdge(node1, node2, 1);
addWeightedEdge(node2, node1, 1);
}
// void print() {
// for (auto& pair : AdjList) {
// for (Edge& edge : pair.second) {
// edge.print();
// }
// }
// }
/**
* @brief Function that checks if a combination of edges is valid
*
* @param star: the combination of edges to check
* @return true if the combination is valid, false otherwise
*
* @details The function checks if the intersection of the sets of nodes reachable from the nodes of the edges in the combination is a singleton
*
*/
bool checkComb(vector<Edge> star) {
auto it = star.begin();
auto v = AdjList[(*it).to];
unordered_set<string> acc;
for (auto& e : v) {
acc.insert(e.to);
}
it++;
for (; it != star.end(); it++) {
auto v = AdjList[(*it).to];
unordered_set<string> s;
for (auto& e : v) {
s.insert(e.to);
}
acc = intersectSets(acc,s);
}
return acc.size() == 1;
}
/**
* @brief Function that finds a solution to the problem
*
* @param c: the number of solutions to find
* @param k: the number of edges in the solution
* @param seed: the seed for the random number generator
* @return a vector of vectors of edges, each vector of edges represents a solution
*
* @details The function iterates over the keys of the adjacency list, shuffles them, and, for each key, it sorts the edges by weight and tries all the combinations of k edges.
* If a combination is valid, it is added to the solution vector
*/
vector<vector<Edge>> findSol(int c, int k, long seed) {
vector<vector<Edge>> Sol;
vector<string> keys = getShuffleKeys(AdjList, seed);
for (auto& key : keys) {
auto edges = AdjList[key];
if (c == 0)
break;
if (edges.size() >= k) {
sort(edges.begin(), edges.end(), compareEdge);
vector<int> indices(k);
iota(indices.begin(), indices.end(), 0); // Fill indices with 0, 1, 2, ..., k - 1
do {
vector<Edge> subV;
for (int i : indices)
subV.push_back(edges[i]);
if (checkComb(subV)) {
c--;
Sol.push_back(subV);
break;
}
} while(!nextComb(indices, edges.size()));
}
}
return Sol;
}
void printSol(vector<vector<Edge>> Sol) {
for (auto& edges : Sol) {
cout << edges[0].from << ":" << " ";
for (auto& edge : edges) {
cout << edge.to << " ";
}
cout << endl;
}
}
};