BOJ/BFS\DFS

[C언어 / 백준 - 1707번] 이분 그래프 (DFS/BFS)

JWonK 2021. 5. 27. 15:40
728x90
반응형

https://www.acmicpc.net/problem/1707

 

1707번: 이분 그래프

입력은 여러 개의 테스트 케이스로 구성되어 있는데, 첫째 줄에 테스트 케이스의 개수 K(2≤K≤5)가 주어진다. 각 테스트 케이스의 첫째 줄에는 그래프의 정점의 개수 V(1≤V≤20,000)와 간선의 개수

www.acmicpc.net

문제

그래프의 정점의 집합을 둘로 분할하여, 각 집합에 속한 정점끼리는 서로 인접하지 않도록 분할할 수 있을 때, 그러한 그래프를 특별히 이분 그래프 (Bipartite Graph) 라 부른다.

그래프가 입력으로 주어졌을 때, 이 그래프가 이분 그래프인지 아닌지 판별하는 프로그램을 작성하시오.

입력

입력은 여러 개의 테스트 케이스로 구성되어 있는데, 첫째 줄에 테스트 케이스의 개수 K(2≤K≤5)가 주어진다. 각 테스트 케이스의 첫째 줄에는 그래프의 정점의 개수 V(1≤V≤20,000)와 간선의 개수 E(1≤E≤200,000)가 빈 칸을 사이에 두고 순서대로 주어진다. 각 정점에는 1부터 V까지 차례로 번호가 붙어 있다. 이어서 둘째 줄부터 E개의 줄에 걸쳐 간선에 대한 정보가 주어지는데, 각 줄에 인접한 두 정점의 번호가 빈 칸을 사이에 두고 주어진다.

출력

K개의 줄에 걸쳐 입력으로 주어진 그래프가 이분 그래프이면 YES, 아니면 NO를 순서대로 출력한다.

 

일단 이 문제를 풀기 위해서는 이분 그래프가 무엇인지 알고 있어야한다

나도 문제를 풀기 전까지 몰랐던 개념이라 구글링을 통해 뭔지부터 알아가야했다.

내가 참고한 블로그 자료 https://woovictory.github.io/2020/01/26/Bipartite-Graph/

 

[알고리즘] 이분 그래프

이분 그래프란? 인접한 정점끼리 서로 다른 색으로 칠해서 모든 정점을 두 가지 색으로만 칠할 수 있는 그래프를 말한다.

woovictory.github.io

 

이분 그래프의 기본적인 개념을 알았다면 문제를 풀면 된다.

일단 이제 인접리스트로 구현한 그래프도 C언어로 구현할 수 있기 때문에 이 문제 또한 인접리스트로 풀었다.

인접리스트로 풀게 될 경우 공간복잡도를 훨씬 효율적으로 문제를 해결할 수 있기 때문이다.

 

문제를 푼 과정은 저 블로그와 똑같이 풀었다.

BFS방식을 사용하였는데 아직 색칠 되어있지 않은 하나의 정점에 들어가 확인하여 색칠해주고 그 정점과 간선으로 연결되어있는 다른 정점을 확인해주는 것이다. 그 중 아직 색칠되어있지 않은 정점은 현재와 다른 색깔로 색칠해주고, 현재와 다른 색깔이 칠해져있다면 넘어간다. 하지만, 현재의 색깔과 같은 색이 칠해져있다는 것은 이분 그래프가 아니라는 것이기때문에 바로 BFS과정을 끝내고 NO를 출력해주는 것이다. 

 

정점을 색칠하는 것을 visited배열을 1과 2로 초기화 해주는 것으로 나타내주었고, 아직 아무색도 칠해져있지 않은 것은 0으로 나타내주었다.

 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define max 20001

typedef struct graphNode {
	int dest;
	struct graphNode* next;
}GraphNode;

typedef struct graph {
	int size;
	GraphNode* adj;
}Graph;

int visited[max];
int V, E;
int u, v;

int Queue[max];
int head = 0, tail = 0;

bool judge_end = false;

void Init_Graph(Graph* gph, int size) {
	gph->size = size;
	gph->adj = (GraphNode*)malloc((size+1) * sizeof(GraphNode));
	for (int i = 1; i <= size; i++)
		gph->adj[i].next = NULL;
}

int AddDirectedEdge(Graph* gph, int src, int dst) {
	GraphNode* temp = (GraphNode*)malloc(sizeof(GraphNode));
	temp->dest = dst;
	temp->next = gph->adj[src].next;
	gph->adj[src].next = temp;
	return 1;
}

int Add_Node_Edge(Graph* gph, int src, int dst) {
	return AddDirectedEdge(gph, src, dst) && AddDirectedEdge(gph, dst, src);
}

void Reset(Graph* gph) {
	gph->size = 0;
    for(int i=1;i<=gph->size;i++)
        gph->adj[i].next=NULL;
}

void Queue_Enque(int data) {
	Queue[tail] = data;
	tail = (tail + 1) % max;
}

int Queue_Deque(void) {
	int cut_data = Queue[head];
	head = (head + 1) % max;
	return cut_data;
}

int Queue_Is_Empty(void) {
	if (head == tail) return 0;
	else return 1;
}

void bfs(Graph* gph, int start) {
	visited[start] = 1;
	
	int curr, destination;
	Queue_Enque(start);

	while (Queue_Is_Empty()) {
		curr = Queue_Deque();
		int now_color_num = 0, prev_color_num = 0;
	
		if (visited[curr] == 1) {
			prev_color_num = 1;
			now_color_num = 2;
		}
		else {
			prev_color_num = 2;
			now_color_num = 1;
		}

		GraphNode* head = gph->adj[curr].next;
		while (head) {
			destination = head->dest;
			if (visited[destination] == prev_color_num) {
				judge_end = true;
				break;
			}
			else if (!visited[destination]) {
				Queue_Enque(destination);
				visited[destination] = now_color_num;
			}
			head = head->next;
		}
	}
}

void PrintGraph(Graph* gph) {
	GraphNode* head;
	printf("Graph size >>> %d\n", gph->size);
	for (int i = 1; i <= gph->size; i++) {
		head = gph->adj[i].next;
		printf(" Node [ %d ] : ", i);
		while (head) {
			printf(" %d ", head->dest);
			head = head->next;
		}
		printf("\n");
	}
}

int main() {
	Graph graph;
	int tc;
	scanf("%d", &tc);

	while (tc--) {
        judge_end = false;
		scanf("%d %d", &V, &E);
		Init_Graph(&graph, V);
		int* check = (int*)calloc(V + 1, sizeof(int));
		for (int i = 0; i < E; i++) {
			scanf("%d %d", &u, &v);
			Add_Node_Edge(&graph, u, v);
			if (!check[u]) check[u] = 1;
			if (!check[v]) check[v] = 1;
		}
		for (int ps = 1; ps <= V; ps++) {
			if (check[ps] && !visited[ps]) {
				bfs(&graph, ps);
			}
		}
		if (judge_end) puts("NO");
		else puts("YES");
		Reset(&graph);
		free(check);
		memset(visited, 0, sizeof(visited));
	}
	return 0;
}

 

 

 

728x90
반응형