Skip to content

Conversation

@kangrae-jo
Copy link
Collaborator

@kangrae-jo kangrae-jo commented Aug 28, 2025

๐Ÿ”— ๋ฌธ์ œ ๋งํฌ

[์›œํ™€]

โœ”๏ธ ์†Œ์š”๋œ ์‹œ๊ฐ„

40m ~ 1h

โœจ ์ˆ˜๋„ ์ฝ”๋“œ

์ €๋Š” ์ด ๋ฌธ์ œ๋ฅผ ์ฝ๊ณ  "์Œ์˜ ์‚ฌ์ดํด"์ด ์žˆ์œผ๋ฉด YES๊ณ , ์•„๋‹ˆ๋ผ๋ฉด NO๋ผ๊ณ  ์ƒ๊ฐํ•˜๊ณ  ๊ทธ๋ ‡๊ฒŒ ์ ‘๊ทผํ–ˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋ž˜์„œ ๋”ฑ ํ•˜๋‚˜์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ๋– ์˜ค๋ฅด๋”๋ผ๊ตฌ์š”.

๋ฐ”๋กœ ๋ฒจ๋งŒ ํฌ๋“œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด์ฃ .
๋ฒจ๋งŒ ํฌ๋“œ๋Š” ์ตœ๋‹จ ๊ฒฝ๋กœ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ค‘ ํ•˜๋‚˜์ด๋ฉฐ, ์Œ์˜ ๊ฐ€์ค‘์น˜๊ฐ€ ์žˆ๋Š” ๊ทธ๋ž˜ํ”„์—์„œ๋„ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๊ตฌํ˜„์„ ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๊นŒ๋จน์–ด์„œ... ๋‹ค์‹œ ๊ณต๋ถ€ํ•˜๊ณ  ํ’€์–ด๋ณด๋А๋ผ ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ ธ์Šต๋‹ˆ๋‹ค.

๋ฒจ๋งŒ ํฌ๋“œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์•„์ด๋””์–ด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์•„์š”.

1. ์ •์  ๊ฐœ์ˆ˜๊ฐ€ N์ผ ๋•Œ, ์ตœ๋‹จ ๊ฒฝ๋กœ๋Š” ์ตœ๋Œ€N -1๊ฐœ์˜ ๊ฐ„์„ ๋งŒ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋‹ค.
2. ๊ฐ„์„ ์„ N-1๋ฒˆ relaxํ•œ๋‹ค๋ฉด ์ตœ๋‹จ ๊ฑฐ๋ฆฌ๊ฐ€ ์™„์„ฑ๋œ๋‹ค.
3. ๋งŒ์•ฝ N๋ฒˆ์งธ์—๋„ ๊ฑฐ๋ฆฌ ๊ฐฑ์‹ ์ด ๋ฐœ์ƒํ•œ๋‹ค๋ฉด -> ๋” ์งง์€ ๊ฒฝ๋กœ๊ฐ€ ๊ณ„์† ์ƒ๊ธด๋‹ค๋Š” ๊ฒƒ -> ์Œ์ˆ˜ ์‚ฌ์ดํด์ด ์กด์žฌํ•œ๋‹ค๋Š” ๊ฒƒ!

์–ด๋•Œ์š” ๊ธ€๋กœ ๋ณด๋‹ˆ๊นŒ ์ดํ•ด๊ฐ€ ์‰ฝ์ฃ ?

์œ„์— relaxation์ด๋ผ๋Š” ํ‘œํ˜„์ด ๋‚˜์™”๋Š”๋ฐ '์™„ํ™”'๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
๋ชจ๋“  ๊ฐ„์„  u ->{ v, w } ์— ๋Œ€ํ•ด์„œ,

if dist[v] > dist[u] + w
    then dist[v] =dist[u] + w

ํ•˜๋Š” ๊ฒƒ์„ ๋งํ•ฉ๋‹ˆ๋‹ค.

์ •์ ์ด N, ๊ฐ„์„ ์ด M์ผ๋•Œ
์ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์‹œ๊ฐ„๋ณต์žก๋„๊ฐ€ O(NM) ์ž…๋‹ˆ๋‹ค.
๋งค ๋ผ์šด๋“œ๋งˆ๋‹ค ๋ชจ๋“  ๊ฐ„์„  M๊ฐœ๋ฅผ ํ›‘๊ณ  ๊ทธ๊ฑธ N-1๋ฒˆ ์ •๋„ ๋ฐ˜๋ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
๋‹ค์ต์ŠคํŠธ๋ผ๋ณด๋‹ค ๋А๋ฆฌ์ง€๋งŒ ์Œ์ˆ˜ ๊ฐ€์ค‘์น˜๋„ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์ฃ .

(์ฐธ๊ณ ๋กœ pq๋กœ ๊ตฌํ˜„ํ•œ ๋‹ค์ต์ŠคํŠธ๋ผ๋Š” O((N + M) log N) ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.)

์ด๋ฒˆ๋ฌธ์ œ๋Š” ๋ฒจ๋งŒ ํฌ๋“œ๋ฅผ boolํƒ€์ž…์œผ๋กœ return ํ•˜๋Š” ๊ฒƒ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ํ’€ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ์˜€๋„ค์š”.
๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“š ์ƒˆ๋กญ๊ฒŒ ์•Œ๊ฒŒ๋œ ๋‚ด์šฉ

๋ฒจ๋งŒ ํฌ๋“œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค.
์ตœ๋‹จ ๊ฑฐ๋ฆฌ๋ฅผ ๊ตฌํ•˜๋Š” ๊ธฐ๋ณธ ์—ฐ์‚ฐ์ธ relaxation์— ๋Œ€ํ•ด์„œ๋„ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค.

image image

ใ„ฑใ…‡ใ…Ž๊ต์ˆ˜๋‹˜์˜ ์ž๋ฃŒ์ž…๋‹ˆ๋‹ค.
๋ณด๊ณ  ๊ตฌํ˜„์„ ํ•œ๊ฑด ์•„๋‹ˆ์ง€๋งŒ ๋ฒจ๋งŒ ํฌ๋“œ๋ฅผ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์— ๋„์›€์ด ๋˜์–ด์„œ ์ฒจ๋ถ€ํ•ฉ๋‹ˆ๋‹ค.

์ž๋ฃŒ์—์„œ๋Š” N-1๋ฒˆ์„ ๊ณ ์ •์œผ๋กœ relaxํ•˜๊ณ ,
์ดํ›„์— ํ•œ๋ฒˆ์”ฉ ๋” relaxํ•ด์„œ true false๋ฅผ ํŒ๋ณ„ํ•˜๋Š” ๊ตฐ์š”.

์ €๋Š” N๋ฒˆ ๋ฐ˜๋ณตํ•˜๋Š”๋ฐ, ์ƒˆ๋กœ relax๋˜๋Š” ์‹œ์ ์ด N๋ฒˆ์งธ์ด๋ฉด return true ํ•˜๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค.
์ทจํ–ฅ์— ๋งž๊ฒŒ ๊ตฌํ˜„ํ•˜์‹œ๋ฉด ๋  ๊ฒƒ ๊ฐ™๋„ค์š”.

Copy link
Collaborator

@g0rnn g0rnn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์˜ค๋ž˜ ๊ธฐ๋‹ค๋ฆฌ์…จ์ฃ ? ใ…‹ใ…‹

์ „ ์ฒ˜์Œ์— ๊ฒฝ๋กœ๋ฅผ ๋Œ์•„๋Œ•๊ธฐ๋ฉด์„œ ์Œ์ˆ˜๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋ ค ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ƒ๊ฐํ•ด๋ณด๋‹ˆ ์‚ฌ์ดํด์ด ์ƒ๊ธฐ๋ฉด ๋ชจ๋“  ๊ฒฝ๋กœ๋ฅผ ์ฐพ์„ ์ˆ˜๊ฐ€ ์—†์ฃ . ๋ฌดํ•œ๋Œ€๋กœ ์ƒ์„ฑ๋˜์ž–์•„์š”.

๊ทธ๋ž˜์„œ ๋‹ต์„ ์ฐธ๊ณ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ฒจ๋งŒ ํฌ๋“œ ๊ฐ•์˜์ž๋ฃŒ๋ฅผ ๋‹ค์‹œ ๋ณด๋‹ˆ ์ตœ๋‹จ ๊ฒฝ๋กœ๋ฅผ ๊ตฌํ•˜๋Š” ๊ฒƒ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์Œ์ˆ˜ ์‚ฌ์ดํด์„ ํ™•์ธํ•  ์ˆ˜๊ฐ€ ์žˆ๋”๊ตฐ์š”. ์˜คํžˆ๋ ค ์Œ์ˆ˜ ์‚ฌ์ดํด์„ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•์ฒ˜๋Ÿผ ๋А๊ปด์กŒ์Šต๋‹ˆ๋‹ค. ๊ทธ๋™์•ˆ ๋‹ค์ต์ŠคํŠธ๋ผ์— ๊ฐ€๋ ค์ ธ์„œ ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š์€ ๋…€์„์ธ๋ฐ ๊ฝค ๊ดœ์ฐฎ์€ ์นœ๊ตฌ์˜€๋‹ค๋Š”๊ฑธ ์•Œ๊ฒŒ ๋˜์—ˆ์–ด์š”.

๊ตฌํ˜„์€ cpp๊ณผ ๋‹ค๋ฅด๊ฒŒ ์ข€ ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค.. ๋ณต์žกํ•˜๋‹ค๊ธฐ ๋ณด๋‹จ ๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ๊ฐ€ ์ข€ ๋งŽ์•„์š”.

package beakjoon;

import java.io.*;
import java.util.*;

public class Sol1865 {
    private static int tc = 0;

    public static void main(String[] args) throws IOException {
        readInput();
    }

    private static void readInput() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        tc = Integer.parseInt(br.readLine());

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < tc; i++) {
            st = new StringTokenizer(br.readLine());
            int n = Integer.parseInt(st.nextToken());
            int m = Integer.parseInt(st.nextToken());
            int w = Integer.parseInt(st.nextToken());

            List<Edge> edges = new ArrayList<>();
            for (int j = 0; j < m; j++) {
                st = new StringTokenizer(br.readLine());
                int s = Integer.parseInt(st.nextToken());
                int e = Integer.parseInt(st.nextToken());
                int t = Integer.parseInt(st.nextToken());

                edges.add(new Edge(s, e, t));
                edges.add(new Edge(e, s, t));
            }

            for (int j = 0; j < w; j++) {
                st = new StringTokenizer(br.readLine());
                int s = Integer.parseInt(st.nextToken());
                int e = Integer.parseInt(st.nextToken());
                int t = Integer.parseInt(st.nextToken());

                edges.add(new Edge(s, e, -t));
            }

            sb.append(hasNegativeCycle(edges, n) ? "YES" : "NO").append('\n');
        }
        System.out.println(sb.toString());
        br.close();
    }

    private static boolean hasNegativeCycle(List<Edge> edges, int n) {
        int[] dist = new int[n + 1]; // 1์—์„œ ์ถœ๋ฐœ!
        Arrays.fill(dist, 0);

        for (int i = 1; i < n; i++) {
            boolean updated = false;
            for (Edge e : edges) {
                if (dist[e.to] > dist[e.from] + e.time) {
                    dist[e.to] = dist[e.from] + e.time;
                    updated = true;
                }
            }
            if (!updated) break;
        }
        for (Edge e : edges) {
            if (dist[e.to] > dist[e.from] + e.time) return true;
        }
        return false;
    }

    static class Edge {
        int from;
        int to;
        int time;

        Edge(int f, int t, int time) {
            from = f;
            to = t;
            this.time = time;
        }
    }
}

๊ทผ๋ฐ ํŠน์ดํ•œ๊ฒŒ ์ด๋…€์„์€ ์Œ์ˆ˜ ์‚ฌ์ดํด์„ ์ฐพ๋Š”๋ฐ์—๋งŒ ํŠนํ™”๋˜์–ด ์žˆ๋”๋ผ๊ตฌ์š”. ๊ทธ๋ž˜์„œ ์Œ์ˆ˜ ์—ฌ๋ถ€์™€ ์ƒ๊ด€์—†์ด ์‚ฌ์ดํด์„ ์ฐพ์„ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ๊ถ๊ธˆํ•ด์กŒ์Šต๋‹ˆ๋‹ค.

์ฐพ์•„๋ณด๋‹ˆ ์ด๋Š” ์œ ๋‹ˆ์˜จ ํŒŒ์ธ๋“œ๋ฅผ ์ด์šฉํ•˜๋”๋ผ๊ตฌ์š”. ์ด๊ฒƒ๋„ ๋ฒจ๋งŒ ํฌ๋“œ์™€ ๋น„์Šทํ•˜๊ฒŒ ์—ฃ์ง€๋ณ„๋กœ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์—ฃ์ง€๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ u, v๋ฅผ union(์ง‘ํ•ฉ์„ ๊ฒฐํ•ฉ)ํ•˜๋‹ค๊ฐ€ u์™€ v์˜ root parent๊ฐ€ ๊ฐ™์œผ๋ฉด ์‚ฌ์ดํด๋กœ ํŒ๋ณ„ํ•ฉ๋‹ˆ๋‹ค. ์ˆ˜๋„์ฝ”๋“œ๋ฅผ ์ ์–ด๋‘˜ํ…Œ๋‹ˆ ์ฐธ๊ณ ํ•˜์‹œ์กฐ

for (auto u, v : edges) {
    if (!union(u, v)) {
        hasCycle = true;
        break;
    }
}

union(int u, int v) {
    parent_u = findParent(u);
    parent_v = findParent(v);
    if (parent_u == parent_v) return false; // ์‚ฌ์ดํด ๋ฐœ์ƒ

    parent[u] = v; // ์„œ๋กœ ๋‹ค๋ฅธ ์ง‘ํ•ฉ์ด๋ฏ€๋กœ ๋‘ ์ง‘ํ•ฉ์„ ํ•ฉ์นจ
    return true;
}

@kangrae-jo kangrae-jo merged commit 59bb9a3 into main Nov 11, 2025
@kangrae-jo kangrae-jo deleted the 34-kangrae-jo branch November 11, 2025 08:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants