/*
Problem: Divide People Into Two Friendly Tables
Company Tag: Media.net OA
Problem Statement:
We are given N people and M friendship connections.
There are 2 tables.
People sitting at the same table must all be friends with each other.
So each table must form a clique.
Return true if all people can be divided into at most 2 groups
such that each group forms a clique.
Constraints:
1 <= N <= 1000
0 <= M <= N * (N - 1) / 2
1 <= friendships[i][0], friendships[i][1] <= N
No duplicate friendship connections.
Brute Force:
Try all possible ways to divide people into 2 groups.
Why Brute Force Fails:
Each person can go to table 1 or table 2.
Total possibilities = 2^N.
Optimized Idea:
If two people are not friends, they cannot sit together.
So I create the complement graph:
Edge exists if two people are NOT friends.
Now each complement edge means:
These two people must be in different groups.
So the problem becomes:
Is the complement graph bipartite?
Explanation Block:
Original problem asks for 2 cliques.
Complement graph converts the problem into 2-coloring:
- Non-friends must get different colors.
- If this is possible, answer is true.
- Otherwise, answer is false.
Dry Run:
N = 4
friendships:
1 - 2
2 - 3
3 - 4
4 - 1
Missing friendships:
1 - 3
2 - 4
Complement graph is bipartite.
Answer = true
Time Complexity:
O(N^2)
Space Complexity:
O(N^2)
*/
#include <bits/stdc++.h>
using namespace std;
bool canDivideIntoTwoFriendlyTables(int n, vector<vector<int>>& friendships) {
vector<vector<int>> isFriend(n, vector<int>(n, 0));
// Mark direct friendship.
for (auto& e : friendships) {
int u = e[0] - 1;
int v = e[1] - 1;
isFriend[u][v] = 1;
isFriend[v][u] = 1;
}
vector<int> color(n, -1);
// Check every component of the complement graph.
for (int start = 0; start < n; start++) {
if (color[start] != -1) {
continue;
}
queue<int> q;
q.push(start);
color[start] = 0;
while (!q.empty()) {
int u = q.front();
q.pop();
for (int v = 0; v < n; v++) {
if (u == v) {
continue;
}
// If they are friends, no edge exists in complement graph.
if (isFriend[u][v]) {
continue;
}
// If they are not friends, they must be in different groups.
if (color[v] == -1) {
color[v] = color[u] ^ 1;
q.push(v);
} else if (color[v] == color[u]) {
// Same color means they are forced into same table,
// but they are not friends.
return false;
}
}
}
}
return true;
}
int main() {
int n = 4;
vector<vector<int>> friendships = {
{1, 2},
{2, 3},
{3, 4},
{4, 1}
};
cout << (canDivideIntoTwoFriendlyTables(n, friendships) ? "true" : "false") << endl;
return 0;
}