I am trying to solve a problem that was given at an exam in a university in my country. It gives me as input a file that contains on the first line 3 numbers:
...and on the second line the relations(m pairs of numbers with the form (a, b) meaning a is friend with b and b is friend with a).
The task is to find the sequence with the maximum length(which is at least k people) in which people are friends with each other as efficiently as possible. If there is no such sequence "NO" will be printed.
Their examples:
data.txt:
5 5 3
1 2 5 1 3 2 4 5 1 4
output:
1 4 5
data.txt:
5 5 4
1 2 5 1 3 2 4 5 1 4
output:
No
data.txt:
11 18 3
1 8 4 7 7 10 11 10 2 1 2 3 8 9 8 3 9 3 9 2 5 6 5 11 1 4 10 6 7 6 2 8 11 7 11 6
output.txt:
2 3 6 7 8 9 10 11
My approach
Friendships in this case can be represented with an undirected graph (for me at least this seems the most logical data structure to use) where vertices represent people and edges represent friendships. To be part of the sequence a vertex needs to have a degree greater than or equal to k - 1.
And that's where I stop. Currently all I can do is eliminate the nodes that don't have a degree of at least k - 1:
#include <iostream>
#include <fstream>
#include <vector>
#include <utility>
#include <algorithm>
std::ifstream f{ "data.txt" };
constexpr size_t LIMIT = 101;
// graph[i][j]: i is friend with j
// short to avoid vector<bool> specialization
std::vector<std::vector<short>> graph(LIMIT, std::vector<short>(LIMIT, 0));
std::vector<int> validNodes;
int numOfNodes, numOfRelationships, sequenceSize;
void Read()
{
f >> numOfNodes >> numOfRelationships >> sequenceSize;
int a;
int b;
for(int i = 1; i <= numOfRelationships; ++i) {
f >> a >> b;
graph[a][b] = graph[b][a] = 1;
}
}
int Degree(int node)
{
int result = 0;
for(int i = 1; i <= numOfNodes; ++i) {
if(i != node && graph[node][i] == 1) {
++result;
}
}
return result;
}
void KeepValidNodes()
{
for(int i = 1; i <= numOfNodes; ++i) {
if(Degree(i) < sequenceSize - 1) {
// Don't add the node to validNodes vector
// "Remove it from the graph" aka it's not friend with anyone
// all nodes that were friends with it now have a lower degree, remove them from the validNodes vector if that's the case
for(int j = 1; j <= numOfNodes; ++j) {
auto findPos = std::find(validNodes.begin(), validNodes.end(), j);
if(findPos != validNodes.end() && Degree(j) - 1 < sequenceSize - 1) {
*findPos = -1;
}
graph[i][j] = graph[j][i] = 0;
}
}
else {
validNodes.push_back(i);
}
}
}
void PrintSequence()
{
bool empty = true;
for(const int& node : validNodes) {
if(node != -1) {
empty = false;
std::cout << node << std::endl;
}
}
if(empty) {
std::cout << "No" << std::endl;
}
}
int main()
{
Read();
KeepValidNodes();
PrintSequence();
}
This works only for their first 2 examples. The only possible solution that I could think of is generating all possible combinations of nodes and see which one satisfies the requirements. How can I solve this problem efficiently as they say?
EDIT:
I am not necessarily looking for a fully working code but I don't even know how I could approach this problem.