백준 1707 - 이분 그래프
2 minute read
문제링크
문제설명
- 그래프의 정점의 집합을 둘로 분할하여, 각 집합에 속한 정점끼리는 서로 인접하지 않도록 분할할 수 있을 때, 그러한 그래프를 특별히 이분 그래프 (Bipartite Graph) 라 부른다.
- 그래프가 입력으로 주어졌을 때, 이 그래프가 이분 그래프인지 아닌지 판별하는 프로그램을 작성하시오.
문제접근
- 이분 그래프란 에서 이분 그래프의 개념을 먼저 파악했다.
- 완전탐색(DFS, BFS) 을 통해 방문하는 노드에는 서로 다른 색을 칠하는데, 만약 인접한 노드에 같은 색이 이미 칠해져 있다면 이분 그래프가 아니다.
- 모든 노드가 하나의 그래프로 이루어지지 않을 수 있고, 이분 그래프끼리는 서로 독립적이기 때문에 언제나 각 집합에 속한 정점끼리는 서로 인접하지 않도록 분할할 수 있다.
구현1 (DFS)
#include <iostream>
#include <vector>
#include <memory.h>
#define MAX_V 20001
using namespace std;
vector<int> graph[MAX_V];
bool visited[MAX_V];
int colorInfo[MAX_V];
bool flag = true;
// color 는 0 과 1만 존재
void dfs(int cnode, int color)
{
for (int i = 0; i < graph[cnode].size(); i++)
{
int nNode = graph[cnode][i];
if (visited[nNode] == true) // 방문한 적이 있는 경우
{
// 현재 노드의 색깔과 인접한 노드의 색깔이 같은 경우 이분 그래프가 아님
if (colorInfo[nNode] == colorInfo[cnode])
{
flag = false;
return;
}
}
else
{
visited[nNode] = true;
colorInfo[nNode] = (int)!color;
dfs(nNode, (int)!color);
}
}
}
void Init()
{
flag = true;
memset(visited, false, sizeof(visited));
memset(colorInfo, 0, sizeof(colorInfo));
for (int i = 0; i < MAX_V; i++)
{
graph[i].clear();
}
}
int main()
{
cin.tie(NULL);
ios_base::sync_with_stdio(false);
int K;
cin >> K;
for (int testCase = 0; testCase < K; testCase++)
{
Init();
int v, e;
cin >> v >> e;
for (int i = 0; i < e; i++)
{
int from, to;
cin >> from >> to;
graph[from].push_back(to);
graph[to].push_back(from);
}
// 색이 정해지지 않은 노드를 찾고 dfs
for (int node = 1; node <= v; node++)
{
if (visited[node] == false)
{
visited[node] = true;
colorInfo[node] = 0;
dfs(node, 0);
}
}
if (flag) cout << "YES\n";
else cout << "NO\n";
}
return 0;
}
구현2(BFS)
#include <iostream>
#include <vector>
#include <memory.h>
#include <queue>
#define MAX_V 20001
using namespace std;
vector<int> graph[MAX_V];
bool visited[MAX_V];
int colorInfo[MAX_V];
bool flag = true;
void bfs(int sNode)
{
queue<pair<int, int>> q;
q.push(make_pair(sNode, 0)); // 첫 노드 색깔은 0으로 칠한다.
visited[sNode] = true;
colorInfo[sNode] = 0;
while (!q.empty())
{
pair<int, int> cNode = q.front();
q.pop();
int cIdx = cNode.first;
int cColor = cNode.second;
for (int i = 0; i < graph[cIdx].size(); i++)
{
int nIdx = graph[cIdx][i];
// 방문한 적이 있는 경우 -> 색깔 확인
if (visited[nIdx] == true)
{
if (colorInfo[nIdx] == cColor)
{
flag = false;
break;
}
}
else
{
int nColor = (int)!cColor;
visited[nIdx] = true;
colorInfo[nIdx] = nColor;
q.push(make_pair(nIdx, nColor));
}
}
if (flag == false) break;
}
}
void Init()
{
flag = true;
memset(visited, false, sizeof(visited));
memset(colorInfo, 0, sizeof(colorInfo));
for (int i = 0; i < MAX_V; i++)
{
graph[i].clear();
}
}
int main()
{
cin.tie(NULL);
ios_base::sync_with_stdio(false);
int K;
cin >> K;
for (int testCase = 0; testCase < K; testCase++)
{
Init();
int v, e;
cin >> v >> e;
for (int i = 0; i < e; i++)
{
int from, to;
cin >> from >> to;
graph[from].push_back(to);
graph[to].push_back(from);
}
// 색이 정해지지 않은 노드를 찾고 bfs
for (int node = 1; node <= v; node++)
{
if (flag == false) break;
if (visited[node] == false) bfs(node);
}
if (flag) cout << "YES\n";
else cout << "NO\n";
}
return 0;
}
Leave a comment