ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Graph] BOJ 13023 : ABCDE
    백준 문제풀이/GRAPH 2019. 7. 18. 08:52
    백준 알고리즘 강의를 토대로 작성된 문제풀이입니다.

    문제


    BOJ 알고리즘 캠프에는 총 N명이 참가하고 있다. 사람들은 0번부터 N-1번으로 번호가 매겨져 있고, 일부 사람들은 친구이다.

    오늘은 다음과 같은 친구 관계를 가진 사람 A, B, C, D, E가 존재하는지 구해보려고 한다.

    • A는 B와 친구다.

    • B는 C와 친구다.

    • C는 D와 친구다.

    • D는 E와 친구다.

    위와 같은 친구 관계가 존재하는지 안하는지 구하는 프로그램을 작성하시오.

    입력


    첫째 줄에 사람의 수 N (5 ≤ N ≤ 2000)과 친구 관계의 수 M (1 ≤ M ≤ 2000)이 주어진다.

    둘째 줄부터 M개의 줄에는 정수 a와 b가 주어지며, a와 b가 친구라는 뜻이다. (0 ≤ a, b ≤ N-1, a ≠ b) 같은 친구 관계가 두 번 이상 주어지는 경우는 없다.

     

    출력


    문제의 조건에 맞는 A, B, C, D, E가 존재하면 1을 없으면 0을 출력한다.

    풀이


     

    문제를 한마디로 정리해보자면

    " 다섯명의 꼬리를 무는 관계를 찾아라. "

    라고 할 수 있다.

     

     

    간단해 보이지만 입력부터 많은 생각을 고려할 필요가 있다.

    우선 3개의 배열을 만든다.

     

     

    1. 인접배열로 그래프의 정보를 저장하는 2차원 배열

    2. 모든 간선을 저장할 배열

    3. 마지막 E 의 관계를 찾기위한 배열

    (3번 배열을 만든 이유는 마지막에 설명)

     

     

    배열을 모두 선언하고 for 문을 통해서 입력을 받을건데

    A 와 B 가 친구라면 A -> B 도 성립되고

    B -> A 도 성립된다. 

     

     

    따라서 이 그래프는 무방향 그래프가 될것이고

    간선을 입력할때 두 방향 모두 입력할 필요가있다.

     

     

    입력이 모두 끝나면 모든 간선을 돌면서 연속적인 친구관계를 찾아야 한다.

    무방향 그래프로 인해서 간선의 개수가 두배가 되었기 때문에

    입력된 간선의 두배만큼 탐색을한다.

     

     

    가장 처음에 i 와 j 번째의 간선 관계를 확인한다.

    이때 선택된 간선의 정점이 한개도 겹치지 않는 두 간선을 찾는다!!.

     

     

    그렇게 되면 사람 A,B,C,D 가 나올것이고

    필연적으로 A - B , C - D 두개의 친구 관계가 생긴다.

     

     

    여기서 우리는 B - C 의 관계만 확인해주면 4개의 연속적인 관계를 확인할 수 있다.

    이 정보는 미리 저장해두었던 인접그래프에서 찾을 수 있다.

     

     

    자, 여기까지 2개의 배열을 사용해서 4개의 연속적인 관계를 확인했다.

    이제 마지막 5번째 친구만 확인하면 된다.

    이건 간단한게 D 의 친구가 앞에서 정해진 A,B,C 만 아니면 된다.

     

     

    이때 우리는 3번째 배열을 사용해서 간단하게 찾을 수 있다.

    3번째 배열은 마치 인접리스트와 느낌이 비슷하기 때문에

    한 정점에 대한 간선을 쉽게 찾을 수 있다.

     

    이렇게 모든 조건이 성립되는 관계가 존제할때 1을 출력한다.

     

     

     

    코드


    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    bool a[2000][2000]; // 그래프
    vector<int> g[2000]; //E 를 쉽게 찾기위한 배열
    vector<pair<int, int>> edges; //간선
    
    int main() {
    	int n, m;
    	cin >> n >> m;
    	for (int i = 0; i < m; i++) {
    		int from, to;
    		cin >> from >> to;
    		edges.push_back({ from, to }); //무방향 그래프
    		edges.push_back({ to, from });
    		a[from][to] = a[to][from] = true;
    		g[from].push_back(to);
    		g[to].push_back(from);
    	}
    	m *= 2; //관계하나에 간선이 두개씩 추가됨
    	for (int i = 0; i < m; i++) {
    		for (int j = 0; j < m; j++) {
    			// A -> B
    			int A = edges[i].first;
    			int B = edges[i].second;
    			// C -> D
    			int C = edges[j].first;
    			int D = edges[j].second;
    			if (A == B || A == C || A == D || B == C || B == D || C == D) {
    				continue;
    			}
    			// B -> C
    			if (!a[B][C]) {
    				continue;
    			}
    			// D -> E
    			for (int E : g[D]) {
    				
    				if (A == E || B == E || C == E || D == E) {
    					continue;
    				}
    				cout << 1 << '\n';
    				return 0;
    			}
    		}
    	}
    	cout << 0 << '\n';
    	return 0;
    }

     

     

    '백준 문제풀이 > GRAPH' 카테고리의 다른 글

    [BFS] BOJ 2178 : 미로 탐색  (0) 2019.08.16
    [BFS] BOJ 4963 : 섬의 개수  (0) 2019.08.15
    [BFS] BOJ 2667 : 단지번호붙이기  (0) 2019.08.14
    [BFS] BOJ 11724 : 연결 요소  (2) 2019.07.24
    [Graph] BOJ 1260 : DFS 와 BFS  (0) 2019.07.22

    댓글

Designed by Tistory.