|
|
@ -12,6 +12,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
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 {
|
|
|
|
struct Edge {
|
|
|
|
string from, to;
|
|
|
|
string from, to;
|
|
|
|
int weight;
|
|
|
|
int weight;
|
|
|
@ -20,11 +28,25 @@ struct Edge {
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @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) {
|
|
|
|
bool compareEdge(Edge e1, Edge e2) {
|
|
|
|
return (e1.weight > e2.weight);
|
|
|
|
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 {
|
|
|
|
class UndirectedWeightedGraph {
|
|
|
|
private:
|
|
|
|
private:
|
|
|
|
void addWeightedEdge(string from, string to, int weight) {
|
|
|
|
void addWeightedEdge(string from, string to, int weight) {
|
|
|
@ -57,6 +79,15 @@ class UndirectedWeightedGraph {
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @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) {
|
|
|
|
bool checkComb(vector<Edge> star) {
|
|
|
|
auto it = star.begin();
|
|
|
|
auto it = star.begin();
|
|
|
|
auto v = AdjList[(*it).to];
|
|
|
|
auto v = AdjList[(*it).to];
|
|
|
@ -79,28 +110,39 @@ class UndirectedWeightedGraph {
|
|
|
|
return acc.size() == 1;
|
|
|
|
return acc.size() == 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
vector<vector<Edge>> findSol(int c, int k) {
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @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<vector<Edge>> Sol;
|
|
|
|
|
|
|
|
|
|
|
|
vector<string> keys = getShuffleKeys(AdjList);
|
|
|
|
vector<string> keys = getShuffleKeys(AdjList, seed);
|
|
|
|
|
|
|
|
|
|
|
|
for (auto& key : keys) {
|
|
|
|
for (auto& key : keys) {
|
|
|
|
auto node = AdjList[key];
|
|
|
|
auto edges = AdjList[key];
|
|
|
|
|
|
|
|
|
|
|
|
if (c == 0)
|
|
|
|
if (c == 0)
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
if (node.size() >= k) {
|
|
|
|
if (edges.size() >= k) {
|
|
|
|
|
|
|
|
|
|
|
|
sort(node.begin(), node.end(), compareEdge);
|
|
|
|
sort(edges.begin(), edges.end(), compareEdge);
|
|
|
|
|
|
|
|
|
|
|
|
vector<int> indices(k);
|
|
|
|
vector<int> indices(k);
|
|
|
|
iota(indices.begin(), indices.end(), 0);
|
|
|
|
iota(indices.begin(), indices.end(), 0); // Fill indices with 0, 1, 2, ..., k - 1
|
|
|
|
do {
|
|
|
|
do {
|
|
|
|
|
|
|
|
|
|
|
|
vector<Edge> subV;
|
|
|
|
vector<Edge> subV;
|
|
|
|
for (int i : indices)
|
|
|
|
for (int i : indices)
|
|
|
|
subV.push_back(node[i]);
|
|
|
|
subV.push_back(edges[i]);
|
|
|
|
|
|
|
|
|
|
|
|
if (checkComb(subV)) {
|
|
|
|
if (checkComb(subV)) {
|
|
|
|
c--;
|
|
|
|
c--;
|
|
|
@ -108,7 +150,7 @@ class UndirectedWeightedGraph {
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} while(!nextComb(indices, node.size()));
|
|
|
|
} while(!nextComb(indices, edges.size()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|