문제 링크 - https://www.acmicpc.net/problem/1976
🌱 문제
🌱 풀이
- 문제에서 요구하는 것은 여행 계획에 속한 도시들이 주어졌을 때, 여행이 가능한지만 판별하면 되는 문제였다.
- 그렇기 때문에 계획으로 주어진 도시들이 연결된 그래프이면 YES이고, 하나라도 연결되어 있지 않으면 NO를 출력하면 되는 꽤 간단한 문제라는 생각이 들었다.
- 그래서 내가 주어진 모든 도시들에 대해서 BFS를 돌렸고, 인접한 도시들과
union&find
를 통해서 조상을 일치시켜 주었다.
- 모든 도시들에 대해 BFS를 마친 후, 여행경로로 주어진 도시들을 탐색하면서 하나라도 조상이 다른 도시가 있다면, 연결되어있지 않은 것이므로 (= 여행할 수 없는 것이므로) NO를 출력하도록 해주었다.
개선할 점
- 아래 부분의 코드를 보면 나는 모든 도시에 대해서, 각 도시가 방문체크 되지 않았다면 전부 BFS를 도는 과정을 하고 있다.
- 또한 인접한 도시를 찾는 과정도 행렬을 탐색하면서 일일이 찾기 때문에 꽤나 비효율적이었다.
for(int i=1; i<=N; i++) {
if(visit[i]==false) {
Queue<Integer> queue = new LinkedList<Integer>();
visit[i]=true;
queue.add(i);
while(!queue.isEmpty()) {
int cur = queue.poll();
for(int j=1; j<=N; j++) {
if(arr[cur][j]==1 && visit[j]==false) {
if(getParent(cur)!=getParent(j)) {
union(cur,j);
visit[j]=true;
queue.add(j);
}
}
}
}
}
}
- 문제를 풀고나서 내 풀이가 맞는지 궁금해서 구글링을 해보았다.
- 모든 도시에 대해서 BFS를 돌지 않고, 단순히 행렬에서 값을 1로 가지는 행과 열에 대해서
union&find
연산을 해주면 좀더 효율적으로 연결된 도시들을 확인할 수 있었다.!
for(int i=1; i<=N; i++) {
for(int j=1; j<=N; j++) {
if(arr[i][j]==1 && parent[i]!=parent[j])
union(i,j);
}
}
🌱 코드 (BFS)
package _2023.Jan_week01;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class boj_1976 {
static int N, M;
static int arr[][];
static int travel[];
static boolean visit[];
static int parent[];
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
N=Integer.parseInt(br.readLine());
M=Integer.parseInt(br.readLine());
arr =new int[N+1][N+1];
travel = new int[M];
visit = new boolean[N+1];
parent = new int[N+1];
for(int i=1; i<=N; i++) {
parent[i]=i;
st= new StringTokenizer(br.readLine());
for(int j=1; j<=N; j++) {
arr[i][j]=Integer.parseInt(st.nextToken());
}
}
st=new StringTokenizer(br.readLine());
for(int i=0; i<M; i++) {
travel[i]=Integer.parseInt(st.nextToken());
}
for(int i=1; i<=N; i++) {
if(visit[i]==false) {
Queue<Integer> queue = new LinkedList<Integer>();
visit[i]=true;
queue.add(i);
while(!queue.isEmpty()) {
int cur = queue.poll();
for(int j=1; j<=N; j++) {
if(arr[cur][j]==1 && visit[j]==false) {
if(getParent(cur)!=getParent(j)) {
union(cur,j);
visit[j]=true;
queue.add(j);
}
}
}
}
}
}
boolean flag = true;
for(int i=0; i<M-1; i++) {
if(getParent(travel[i])!=getParent(travel[i+1])) {
flag=false;
break;
}
}
if(flag==true)
System.out.println("YES");
else
System.out.println("NO");
}
public static int getParent(int x) {
if(parent[x]==x)
return x;
return parent[x]=getParent(parent[x]);
}
public static void union(int x, int y) {
x=getParent(x);
y=getParent(y);
if(x>y)
parent[x]=y;
else
parent[y]=x;
}
}
🌱 수정한 코드
package _2023.Jan_week01;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class boj_1976 {
static int N, M;
static int arr[][];
static int travel[];
static boolean visit[];
static int parent[];
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
N=Integer.parseInt(br.readLine());
M=Integer.parseInt(br.readLine());
arr =new int[N+1][N+1];
travel = new int[M];
visit = new boolean[N+1];
parent = new int[N+1];
for(int i=1; i<=N; i++) {
parent[i]=i;
st= new StringTokenizer(br.readLine());
for(int j=1; j<=N; j++) {
arr[i][j]=Integer.parseInt(st.nextToken());
}
}
st=new StringTokenizer(br.readLine());
for(int i=0; i<M; i++) {
travel[i]=Integer.parseInt(st.nextToken());
}
for(int i=1; i<=N; i++) {
for(int j=1; j<=N; j++) {
if(arr[i][j]==1 && parent[i]!=parent[j])
union(i,j);
}
}
boolean flag = true;
for(int i=0; i<M-1; i++) {
if(getParent(travel[i])!=getParent(travel[i+1])) {
flag=false;
break;
}
}
if(flag==true)
System.out.println("YES");
else
System.out.println("NO");
}
public static int getParent(int x) {
if(parent[x]==x)
return x;
return parent[x]=getParent(parent[x]);
}
public static void union(int x, int y) {
x=getParent(x);
y=getParent(y);
if(x>y)
parent[x]=y;
else
parent[y]=x;
}
}