https://www.acmicpc.net/problem/11403
11403번: 경로 찾기
가중치 없는 방향 그래프 G가 주어졌을 때, 모든 정점 (i, j)에 대해서, i에서 j로 가는 경로가 있는지 없는지 구하는 프로그램을 작성하시오.
www.acmicpc.net
풀이)
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.StringTokenizer;
public class Main_BJ_11403_경로찾기 {
static int[][] adj;
static int n;
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
n = Integer.parseInt(br.readLine());
adj = new int[n][n];
int[][] ans = new int[n][n];
for(int i=0; i<n; i++){
StringTokenizer st = new StringTokenizer(br.readLine());
for(int j=0; j<n; j++){
adj[i][j] = Integer.parseInt(st.nextToken());
}
}
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
if(route(i, j))
ans[i][j] = 1;
else
ans[i][j] = 0;
}
}
StringBuilder sb = new StringBuilder();
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
sb.append(ans[i][j]+" ");
}
sb.append("\n");
}
System.out.print(sb);
}//main
private static boolean route(int start, int end){
boolean[] visited = new boolean[n];
Queue<Integer> q = new ArrayDeque<>();
q.offer(start);
// visited[start] = true;
while(!q.isEmpty()){
int cur = q.poll();
for(int i=0; i<n; i++){
if(adj[cur][i]==1 && !visited[i]){
q.add(i);
visited[i] = true;
}
}
}
if(visited[end])
return true;
return false;
}//route
}
이 문제가 플로이드-워셜 문제인걸 풀고 나서 알았다...
다시 공부해서 올려야징
나는 플로이드로 풀진 않았고, bfs랑 비슷한 논리를 사용해서 했다.
이때, 주의할점은 start == end 일 수 있으므로, 큐에 처음 넣을 때 방문처리를 하지 않아야 한다.
또한 queue에서 꺼낸 값 cur이 end와 같다해서 바로 true를 리턴하면 안된다...
처음엔 당연히 출발==도착이면 방문할 수 있을줄 알았다ㅋㅋㅋ
풀이2) 플로이드-워셜 알고리즘
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.StringTokenizer;
public class Main_BJ_11403_경로찾기 {
static int[][] adj;
static int n;
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
n = Integer.parseInt(br.readLine());
adj = new int[n][n];
int[][] ans = new int[n][n];
for(int i=0; i<n; i++){
StringTokenizer st = new StringTokenizer(br.readLine());
for(int j=0; j<n; j++){
adj[i][j] = Integer.parseInt(st.nextToken());
}
}
//단순히 가는 것만 체크
for(int k=0; k<n; k++){
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
if(adj[i][k] == 1 & adj[k][j]==1)
adj[i][j] = 1;
}
}
}
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
System.out.print(adj[i][j]+" ");
}
System.out.println();
}
}//main
}
이 문제는 플로이드 워셜로 풀면 훨씬 시간이 단축된다.
애초에 간선에 가중치도 없었고, 문제 자체도 연결 되었는지 아닌지만 파악하면 되기 때문!
따라서 adj[i][k] == 1 && adj[k][j]==1의 조건만 있으면 된다.
플로이드-워셜 간단 정리
- 모든 정점에서 모든 정점까지의 최단 거리를 구할 때 사용
- 음수 사이클이 없어야함
- 인접행렬 이용
- 본인과 본인의 거리는 최소 0이라고 판단
- 본인과 연결되지 않은 정점은 최대로 넣어줌
- 차례대로 정점을 1개 거치고,,, 2개 거치고,,, n개를 거치는 경우가 가능함.
- 즉, 바로 연결된 정점을 가느냐 vs k 정점을 거쳐서 가느냐(이것 또한 계속 갱신된것)
- adj[i][j] = Math.min(adj[i][j], adj[i][k]+adj[k][j])와 같음
참고한 블로그는 다음과 같다.
https://sskl660.tistory.com/61
[Java]플로이드-워셜 알고리즘(Floyd-Warshall Algorithm)
*플로이드-워셜 알고리즘(Floyd-Warshall Algorithm) -> 플로이드-워셜 알고리즘은 음수 사이클이 없는 그래프내의 각 모든 정점에서 각 모든 정점에 까지의 최단거리를 모두 구할 수 있는 알고리즘이다
sskl660.tistory.com
'코테 > 백준' 카테고리의 다른 글
백준 14500 테트로미노(JAVA) (0) | 2023.02.05 |
---|---|
백준 1780 종이의 개수(JAVA) (0) | 2023.02.04 |
백준 9375 패션왕 신해빈(JAVA) (0) | 2023.02.02 |
백준 11727 2xn 타일링 2(JAVA) (0) | 2023.02.01 |
백준 2178 미로 탐색(JAVA) (0) | 2023.01.31 |