[Algorithm] 백준 1238 : 파티

image

백준 1238 파티

문제 정의 : Directed Graph에서, 모든 노드에 대해 X에 방문했다가 다시 돌아오는 경로의 최소 비용을 구하라.

(1) 모든 노드에서 X로 가는 최소 비용 + (2) X에서 모든 노드로 가는 최소 비용의 합.

  • Dijkstra 알고리즘은 한 노드에서 다른 모든 노드로 가는 Shortest Path를 구할 수 있다.
  • (1)을 구하기 위해, edge의 방향을 반대로 하여 X에서 모든 노드로 가는 Shortest Path를 구한다.
  • (2)를 구하기 위해, 원래 edge 방향 그대로 X에서 모든 노드로 가는 Shortest Path를 구한다.
  • (1)과 (2)에서 각 노드의 d[]를 구한 다음 합한다. 이 중 최대값이 가장 거리가 먼 노드의 비용이다.



Java Code

import java.util.LinkedList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Scanner;

class edge_Party {
    int adj, t;
    edge_Party(int adj, int t) {
        this.adj = adj; this.t = t;
    }
}
class node_Party implements Comparable<node_Party> {
    int v, t;
    node_Party(int v, int t) {
        this.v = v; this.t = t;
    }

    @Override
    public int compareTo(node_Party o) {
        if(o.t<this.t) return 1;
        else if(o.t>this.t) return -1;
        else return 0;
    }
}

public class Main {
    static Scanner in = new Scanner(System.in);
    static int n, m, x;
    static int[][] d = new int[1001][2];
    static int[] visited = new int[1001];
    static PriorityQueue<node_Party> pq = new PriorityQueue<>();
    static PriorityQueue<node_Party> pq_reverse = new PriorityQueue<>();
    static List<edge_Party>[] edges = new List[1001];
    static List<edge_Party>[] edges_reverse = new List[1001];
    public static void main(String[] args) {
        n = in.nextInt(); m = in.nextInt(); x = in.nextInt();
        for(int i=1;i<=n;i++) {
            edges[i] = new LinkedList<>();
            edges_reverse[i] = new LinkedList<>();
            d[i][0] = Integer.MAX_VALUE;
            d[i][1] = Integer.MAX_VALUE;
        }
        for(int i=0;i<m;i++) {
            int v1 = in.nextInt(); int v2 = in.nextInt(); int t = in.nextInt();
            edges[v1].add(new edge_Party(v2, t));
            edges_reverse[v2].add(new edge_Party(v1, t));
            if(v1==x) {
                d[v2][0] = t;
                pq.add(new node_Party(v2, t));
            }
            else if(v2==x) {
                d[v1][1] = t;
                pq_reverse.add(new node_Party(v1, t));
            }
        }
//        1. x에서 모든 정점으로 가는 최소 비용 (d[node][0], edges)
//        2. 모든 정점에서 x로 가는 최소 비용 (d[node][1], edges_reverse)
        int cnt = 1;
        while (cnt<n) {
            node_Party curr = pq.poll();
            if(visited[curr.v]==0) {
                for(int i=0;i<edges[curr.v].size();i++) {
                    int adj = edges[curr.v].get(i).adj;
                    int time = edges[curr.v].get(i).t;

                    if(adj!=x) {
                        d[adj][0] = Math.min(d[adj][0], d[curr.v][0]+time);
                        pq.add(new node_Party(adj, d[adj][0]));
                    }
                }
                visited[curr.v] = 1;
                cnt++;
            }

        }
        for(int i=1;i<=n;i++) {
            visited[i] = 0;
        }
        cnt = 1;
        while (cnt<n) {
            node_Party curr = pq_reverse.poll();
            if(visited[curr.v]==0) {
                for(int i=0;i<edges_reverse[curr.v].size();i++) {
                    int adj = edges_reverse[curr.v].get(i).adj;
                    int time = edges_reverse[curr.v].get(i).t;
                    if(adj!=x) {
                        d[adj][1] = Math.min(d[adj][1], d[curr.v][1]+time);
                        pq_reverse.add(new node_Party(adj, d[adj][1]));

                    }
                }
                visited[curr.v] = 1;
                cnt++;
            }
        } 
        int res = 0;
        for(int i=1;i<=n;i++) {
            if(i!=x) {
                res = Math.max(res, d[i][0]+d[i][1]);
            }
        }
        System.out.println(res);
    }
}