반응형
[ 문제 ]
오늘도 서준이는 깊이 우선 탐색(DFS) 수업 조교를 하고 있다. 아빠가 수업한 내용을 학생들이 잘 이해했는지 문제를 통해서 확인해보자.
N개의 정점과 M개의 간선으로 구성된 무방향 그래프(undirected graph)가 주어진다. 정점 번호는 1번부터 N번이고 모든 간선의 가중치는 1이다. 정점 R에서 시작하여 깊이 우선 탐색으로 노드를 방문할 경우 노드의 방문 순서를 출력하자.
깊이 우선 탐색 의사 코드는 다음과 같다. 인접 정점은 오름차순으로 방문한다.
dfs(V, E, R) { # V : 정점 집합, E : 간선 집합, R : 시작 정점
visited[R] <- YES; # 시작 정점 R을 방문 했다고 표시한다.
for each x ∈ E(R) # E(R) : 정점 R의 인접 정점 집합.(정점 번호를 오름차순으로 방문한다)
if (visited[x] = NO) then dfs(V, E, x);
}
[ 코드 ]
1. 내 코드
StreamReader sr = new StreamReader(Console.OpenStandardInput());
StreamWriter sw = new StreamWriter(Console.OpenStandardOutput());
string[] input = sr.ReadLine().Split();
int N = int.Parse(input[0]);
int M = int.Parse(input[1]);
int R = int.Parse(input[2]);
bool[] visited = new bool[N + 1];
int[] order = new int[N + 1];
List<int>[] graph = new List<int>[N + 1];
for (int i = 1; i <= N; i++)
{
graph[i] = new List<int>();
}
for (int i = 0; i < M; i++)
{
string[] edge = sr.ReadLine().Split();
int u = int.Parse(edge[0]);
int v = int.Parse(edge[1]);
graph[u].Add(v);
graph[v].Add(u);
}
int count = 1;
DFS(graph, R, visited, order, ref count);
for (int i = 1; i <= N; i++)
{
sw.WriteLine(visited[i] ? order[i] : 0);
}
sw.Flush();
sw.Close();
sr.Close();
void DFS(List<int>[] graph, int v, bool[] visited, int[] order, ref int count)
{
visited[v] = true;
order[v] = count++;
foreach (int u in graph[v].OrderBy(x => x))
{
if (!visited[u])
{
DFS(graph, u, visited, order, ref count);
}
}
}
2. 다른 사람 코드
var reader = new Reader(); // Reader 객체 생성
int N = reader.NextInt(); // 정점의 수 입력
int M = reader.NextInt(); // 간선의 수 입력
int R = reader.NextInt(); // 시작 정점 입력
var edges = new PriorityQueue<int, int>[N + 1]; // 우선순위 큐 배열 선언 및 초기화
while (M-- > 0) // 간선 정보 입력 반복문
{
int u = reader.NextInt(); // 첫 번째 정점 입력
int v = reader.NextInt(); // 두 번째 정점 입력
edges[u] = edges[u] ?? new(); // 정점 u에 해당하는 우선순위 큐 생성
edges[v] = edges[v] ?? new(); // 정점 v에 해당하는 우선순위 큐 생성
edges[u].Enqueue(v, v); // u와 v를 연결하는 간선을 우선순위 큐에 추가
edges[v].Enqueue(u, u); // v와 u를 연결하는 간선을 우선순위 큐에 추가 (무방향 그래프이므로)
}
var visited = new int[N + 1]; // 각 정점의 방문 순서를 저장하는 배열
int num = 0; // 방문 순서를 나타내는 변수
DFS(R); // DFS 실행
using (var writer = new StreamWriter(new BufferedStream(Console.OpenStandardOutput()))) // 출력을 위한 StreamWriter 생성
for (int i = 1; i <= N; i++) // 모든 정점에 대해 방문 순서 출력
writer.WriteLine(visited[i]); // 각 정점의 방문 순서를 파일에 씀
void DFS(int node) // 깊이 우선 탐색 함수
{
visited[node] = ++num; // 현재 노드의 방문 순서 기록
while (edges[node]?.Count > 0) // 현재 노드와 연결된 간선이 있는 동안 반복
{
var next = edges[node].Dequeue(); // 현재 노드와 연결된 간선 중 하나를 가져옴
if (visited[next] == 0) // 방문하지 않은 노드일 경우
DFS(next); // 해당 노드에서 DFS 실행
}
}
class Reader // 입력을 처리하는 클래스
{
StreamReader reader; // 스트림 리더 객체
public Reader() // 생성자
{
BufferedStream stream = new(Console.OpenStandardInput()); // 버퍼링된 입력 스트림 생성
reader = new(stream); // 스트림 리더 객체 생성
}
public int NextInt() // 정수 입력을 처리하는 메서드
{
bool negative = false; // 음수 여부를 나타내는 플래그
bool reading = false; // 숫자를 읽고 있는지 여부를 나타내는 플래그
int value = 0; // 입력된 정수값을 저장할 변수
while (true) // 무한 루프
{
int c = reader.Read(); // 다음 문자를 읽음
if (reading == false && c == '-') // 첫 문자가 '-'인 경우
{
negative = true; // 음수 플래그를 설정
reading = true; // 숫자 읽기 플래그를 설정
continue; // 다음 문자 처리로 이동
}
if ('0' <= c && c <= '9') // 문자가 숫자인 경우
{
value = value * 10 + (c - '0'); // 정수로 변환하여 값을 갱신
reading = true; // 숫자 읽기 플래그를 설정
continue; // 다음 문자 처리로 이동
}
if (reading == true) // 숫자를 읽고 있는 상태인 경우
break; // 숫자를 모두 읽은 후 루프 탈출
}
return negative ? -value : value; // 양수일 경우 값을 그대로 반환하고, 음수일 경우 음수로 반환
}
}
지피티한테 주석 달아달라고 부탁했읍니다.
내 코드 말고 다른 코드도 읽고 집중을 해야하는데 집중력이 떨어지네요........... 헤헤
[ 실행화면 ]
문제링크: https://www.acmicpc.net/problem/24479
반응형
'Language > C#' 카테고리의 다른 글
[C#] 백준 1526번 가장 큰 금민수 (0) | 2024.04.13 |
---|---|
[C#] 백준 1260번 DFS와 BFS (0) | 2024.04.12 |
[C#] 백준 1032번 명령 프롬프트 (0) | 2024.04.09 |
[C#] 백준 2606번 바이러스 (0) | 2024.04.08 |
[C#] 백준 1065번 한수 (1) | 2024.04.07 |