코테/백준

[BOJ] 1865 웜홀(Java)

zsunny 2025. 1. 29. 23:28

https://www.acmicpc.net/problem/1865

 

사용 알고리즘

벨만-포드

 

아이디어

1. 웜홀은 음의 간선치

2. 간선 수(N-1) 만큼 거리의 최솟값 구하기

3. N번째 최솟값에 변동이 생기면 음의 사이클 -> 시간이 되돌아감

 

유의점

1. 모든 지점이 연결되어 있지 않을 수 있음. 가상의 지점 0에서 각 지점으로 모두 가중치 0으로 연결시키기

 

제출코드

package BOJ.Graph.BellmanFord;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;

public class BOJ_1865_웜홀 {

    static class Point{
        int x, y;
        int d;
        Point(int x, int y, int d){
            this.x = x;
            this.y = y;
            this.d = d;
        }
    }

    static int n, m, w;
    static final int INF = Integer.MAX_VALUE;
    static List<Point> list;
    static int[] dis;

    public static boolean bellmanford(){
        dis[0] = 0;
        // n-1 만큼 최단거리 구하기
        for(int i=0; i<n; i++){
            for(Point p : list){
                if(dis[p.x] != INF && dis[p.y] > dis[p.x] + p.d){
                    dis[p.y] = dis[p.x] + p.d;
                }
            }
        }
        // 음의 싸이클 확인
        for(Point p : list){
            if(dis[p.x] != INF && dis[p.y] > dis[p.x] + p.d) return true;
        }
        return false;
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        StringTokenizer st;
        int T = Integer.parseInt(br.readLine());

        for(int t=0; t<T; t++){
            st = new StringTokenizer(br.readLine());
            n = Integer.parseInt(st.nextToken());       // 노드 수
            m = Integer.parseInt(st.nextToken());       // 간선 수
            w = Integer.parseInt(st.nextToken());       // 웜홀 수
            list = new ArrayList<>();
            // 간선 정보
            for(int i=0; i<m; i++){
                st = new StringTokenizer(br.readLine());
                int s = Integer.parseInt(st.nextToken());
                int e = Integer.parseInt(st.nextToken());
                int d = Integer.parseInt(st.nextToken());
                list.add(new Point(s, e, d));
                list.add(new Point(e, s, d));
            }
            // 웜홀 정보
            for(int i=0; i<w; i++){
                st = new StringTokenizer(br.readLine());
                int s = Integer.parseInt(st.nextToken());
                int e = Integer.parseInt(st.nextToken());
                int d = Integer.parseInt(st.nextToken());
                list.add(new Point(s, e, -d));
            }
            // 가상의 0번 노드 모든 정점과 연결
            for(int i=1; i<n+1; i++){
                list.add(new Point(0, i, 0));
            }
            dis = new int[n+1];
            Arrays.fill(dis, INF);
            if(bellmanford()) sb.append("YES").append("\n");
            else sb.append("NO").append("\n");
        }
        System.out.println(sb.toString());
    }
}