문제 링크
난이도 : Lv. 3

문제 내용

문제 설명

네트워크란 컴퓨터 상호 간에 정보를 교환할 수 있도록 연결된 형태를 의미합니다. 예를 들어, 컴퓨터 A와 컴퓨터 B가 직접적으로 연결되어있고, 컴퓨터 B와 컴퓨터 C가 직접적으로 연결되어 있을 때 컴퓨터 A와 컴퓨터 C도 간접적으로 연결되어 정보를 교환할 수 있습니다. 따라서 컴퓨터 A, B, C는 모두 같은 네트워크 상에 있다고 할 수 있습니다.

컴퓨터의 개수 n, 연결에 대한 정보가 담긴 2차원 배열 computers가 매개변수로 주어질 때, 네트워크의 개수를 return 하도록 solution 함수를 작성하시오.

제한사항
  • 컴퓨터의 개수 n은 1 이상 200 이하인 자연수입니다.
  • 각 컴퓨터는 0부터 n-1인 정수로 표현합니다.
  • i번 컴퓨터와 j번 컴퓨터가 연결되어 있으면 computers[i][j]를 1로 표현합니다.
  • computer[i][i]는 항상 1입니다.
입출력 예
ncomputersreturn
3[[1, 1, 0], [1, 1, 0], [0, 0, 1]]2
3[[1, 1, 0], [1, 1, 1], [0, 1, 1]]1
입출력 예 설명

예제 #1
아래와 같이 2개의 네트워크가 있습니다.
image0.png

예제 #2
아래와 같이 1개의 네트워크가 있습니다.
image1.png

문제 분석

DFS를 몇 번 돌려야 하는가? 가 정답인듯.

작성한 코드

#include <string>
#include <vector>
#include <stack>
#include <iostream>
 
using namespace std;
 
vector<bool> visited;
stack<int> nextNodes;
 
 
void dfs(vector<vector<int>> &maps, int node)
{
    if(visited[node]) return;
    
    visited[node] = true;
    
    for(int i = 0; i < maps[node].size(); i++)
    {
        if(maps[node][i] == 1 && !visited[i] && i != node)
        {
            nextNodes.push(i);
        }
    }
    
    if(nextNodes.empty()) return;
    
    int nextNode = nextNodes.top();
    nextNodes.pop();
    
    dfs(maps, nextNode);
}
 
int solution(int n, vector<vector<int>> computers) {
    visited.assign(n, false);
    int answer = 0;
    
    bool isDone = false;
    while(!isDone)
    {
        for(int i = 0; i < n; i++)
        {
            if(!visited[i])
            {
                answer++;
                dfs(computers, i);
                break;
            }
            else if (i == n-1) isDone = true;
        }
    }
    return answer;
}
  • 테스트 케이스는 통과했는데, 실제 채점에서 약 7개 정도 틀림.. 왜인지 모르겠음

Chatgpt의 분석

✔ 네가 빼먹은 핵심 포인트 1

DFS 흐름을 “스택 하나”로만 이어가고 있음 → 한 네트워크의 모든 노드를 끝까지 방문하지 못함

너는 다음 노드를 스택에서 딱 하나만 pop 해서 DFS를 이어가고 있어.
문제는 그 하나를 방문한 뒤, 그 노드에서 또 발견된 인접 노드들은 다시 push만 하고, 바로 다음으로 가지 않음.

즉,

  • 인접한 노드는 push

  • “스택이 비면 끝”

  • 스택에서 하나만 뽑아서 재귀

  • 다시 그 재귀 안에서도 하나만 뽑아서 재귀

이 흐름 때문에 한 레벨씩만 내려가고, 다른 자식 노드들은 나중에 처리되지 않음.
→ 결국 한 네트워크 안의 노드를 모두 방문하지 못해 컴포넌트 개수가 늘어남.


✔ 네가 빼먹은 핵심 포인트 2

스택을 지역적으로 사용하지 않고 전역으로 둠 → 이전 네트워크의 잔여 노드가 다음 DFS에 섞임

전역 nextNodes에 계속 push만 하고, 네트워크 하나 끝났을 때 스택을 비우는 로직이 없음.

그래서

  • 첫 DFS에서 넣어둔 node들이 남아 있고

  • 다음 네트워크 탐색 시 그 leftover가 섞임

  • 방문해야 하는 범위가 꼬이거나 잘못된 컴포넌트 수 계산으로 이어짐.


✔ 네가 착각한 포인트

“스택 DFS”라고 해서 stack + recursion을 혼용하면 안 됨

재귀 DFS는 call stack만으로 충분하고,
stack DFS는 while(stack) 구조로 이루어져야 함.

지금처럼 “전역 스택에 push → 재귀한 번 → push → 재귀한 번” 구조는 DFS의 핵심인 모든 인접 노드 순차 방문이 누락됨.


✔ 요약

너의 코드는 결국 두 가지를 놓쳤음.

  1. 스택에 넣은 모든 노드를 DFS로 방문하는 루프가 없음

  2. 스택을 한 DFS(= 한 네트워크)마다 초기화하지 않음

이 두 가지 때문에 네트워크를 온전히 탐색하지 못하는 게 핵심 오류임.

그래서 바꾼 코드

#include <string>
#include <vector>
#include <stack>
#include <iostream>
 
using namespace std;
 
vector<bool> visited;
stack<int> nextNodes;
 
 
void dfs(vector<vector<int>> &maps, int node)
{
    if(visited[node]) return;
    
    visited[node] = true;
    
    for(int i = 0; i < maps[node].size(); i++)
    {
        if(maps[node][i] == 1 && !visited[i] && i != node)
        {
            nextNodes.push(i);
        }
    }
    
    while(!nextNodes.empty())
    {
        int nextNode = nextNodes.top();
        nextNodes.pop();
    
        dfs(maps, nextNode);
    }
}
 
int solution(int n, vector<vector<int>> computers) {
    visited.assign(n, false);
    int answer = 0;
    
    bool isDone = false;
    while(!isDone)
    {
        for(int i = 0; i < n; i++)
        {
            if(!visited[i])
            {
                answer++;
                while(!nextNodes.empty()) nextNodes.pop();
                dfs(computers, i);
                break;
            }
            else if (i == n-1) isDone = true;
        }
    }
    return answer;
}

우수 코드 분석

#include<string>
#include<vector>
 
using namespace std;
 
vector<bool> visited;
 
void dfs(const vector<vector<int>> &network, int node)
{
	visited[node] = true;
	
	for (int i = 0; i < network[node].size(); i++)
	{
		if(network[node][i] && !visited[i])
			dfs(network, i);
	}
}
 
int solution(int n, vector<vector<int>> computers)
{
	visited = vector<bool>(computers.size(), false);
	
	int networkCount = 0;
	
	for(int i = 0 ; i < computers.size(); i++)
	{
		if(!visited[i])
		{
			dfs(computers, i);
			networkCount++;
		}
	}
}