<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>hong0708</title>
    <link>https://hong0708.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Fri, 8 May 2026 10:40:56 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>hong0708</managingEditor>
    <item>
      <title>local.propertites에 api key 값 저장하기</title>
      <link>https://hong0708.tistory.com/entry/localpropertites%EC%97%90-api-key-%EA%B0%92-%EC%A0%80%EC%9E%A5%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. local.propertites에 api key 값 저장하기 이전 gitignore 파일을 수정해야합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 gitignore 파일 코드를 수정합니다.&lt;/p&gt;
&lt;div style=&quot;background-color: #2b2b2b; color: #a9b7c6;&quot;&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;# Gradle files
.gradle
.gradle/
build/

# Signing files
.signing/

# Local configuration file (sdk path, etc)
local.properties&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. local.propertites에 api key 값 저장합니다.&lt;/b&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #2b2b2b; color: #a9b7c6;&quot;&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;sdk.dir=C\:\\Users...
googleMapKey=&quot;1234example1234&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3. build.gradle.kts (Module :app) local.propertites에 있는 값을 가져오는 코드와 manifestPlaceholders를 추가합니다.&lt;/b&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #2b2b2b; color: #a9b7c6;&quot;&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;import java.util.Properties

plugins {
	...
}

android {
    ...

    defaultConfig {
        ...
        
	val properties = Properties()
	properties.load(project.rootProject.file(&quot;local.properties&quot;).inputStream())
        
        manifestPlaceholders[&quot;GOOGLE_MAP_KEY&quot;] = properties[&quot;googleMapKey&quot;] as String
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            ...
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4. manifest 에서 해당 키 값을 활용합니다.&lt;/b&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #2b2b2b; color: #a9b7c6;&quot;&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;&amp;lt;meta-data
    android:name=&quot;com.google.android.geo.API_KEY&quot;
    android:value=&quot;${GOOGLE_MAP_KEY}&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Android</category>
      <author>hong0708</author>
      <guid isPermaLink="true">https://hong0708.tistory.com/33</guid>
      <comments>https://hong0708.tistory.com/entry/localpropertites%EC%97%90-api-key-%EA%B0%92-%EC%A0%80%EC%9E%A5%ED%95%98%EA%B8%B0#entry33comment</comments>
      <pubDate>Thu, 23 Nov 2023 16:19:24 +0900</pubDate>
    </item>
    <item>
      <title>안드로이드 라이브러리 없이 직선 그래프 만들기</title>
      <link>https://hong0708.tistory.com/entry/%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EC%97%86%EC%9D%B4-%EC%A7%81%EC%84%A0-%EA%B7%B8%EB%9E%98%ED%94%84-%EA%B7%B8%EB%A6%AC%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;그래프 그리는 커스텀 뷰 클래스 예제입니다.&lt;br /&gt;직선들을 통한 예제로 부가적으로 필요한 데이터에 맞게 추가하여 직선 그래프를 그리면 해결 가능합니다.&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;package com.example.linegraph

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Point
import android.util.AttributeSet
import android.view.View

class CustomLineGraphView(context: Context, attrs: AttributeSet?) : View(context, attrs) {

    // 직선의 시작과 끝 좌표
    /*private val startX = 100f
    private val startY = 200f
    private val endX = 400f
    private val endY = 200f

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        val paint = Paint()
        paint.color = Color.BLUE
        paint.strokeWidth = 5f

        // 직선 그리기
        canvas.drawLine(startX, startY, endX, endY, paint)
    }*/

    private val linePaint = Paint()
    private var startPoint = Point(0, 0)
    // 아래로 내려가는 직선
    private var endPoint = Point(200, 100)

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        // 화면의 폭에 따라 선의 길이 조절
        val screenWidth = width
        val screenHeight = height
        endPoint.x = screenWidth / 6
        startPoint.y = screenHeight / 2

        linePaint.color = Color.BLUE
        linePaint.strokeWidth = 5f

        // 상대 좌표로 직선 그리기
        // 데이터 값만 잘 받아서 상대 그래프로 충분히 활용은 가능하다.
        // 라이브러리가 있으니 해당 라이브러리 사용이 빠르긴하다.
        canvas.drawLine(startPoint.x.toFloat(), startPoint.y.toFloat(), endPoint.x.toFloat(), endPoint.y.toFloat(), linePaint)
        startPoint.x = endPoint.x
        startPoint.y = endPoint.y
        endPoint.x += screenWidth / 6
        endPoint.y = 4 * endPoint.y
        canvas.drawLine(startPoint.x.toFloat(), startPoint.y.toFloat(), endPoint.x.toFloat(), endPoint.y.toFloat(), linePaint)
        startPoint.x = endPoint.x
        startPoint.y = endPoint.y
        endPoint.x += screenWidth / 6
        endPoint.y = 4 * endPoint.y
        canvas.drawLine(startPoint.x.toFloat(), startPoint.y.toFloat(), endPoint.x.toFloat(), endPoint.y.toFloat(), linePaint)

        startPoint.x = endPoint.x
        startPoint.y = endPoint.y
        endPoint.x += screenWidth / 6
        endPoint.y = screenHeight / 4
        canvas.drawLine(startPoint.x.toFloat(), startPoint.y.toFloat(), endPoint.x.toFloat(), endPoint.y.toFloat(), linePaint)
        startPoint.x = endPoint.x
        startPoint.y = endPoint.y
        endPoint.x += screenWidth / 6
        endPoint.y = screenHeight / 2
        canvas.drawLine(startPoint.x.toFloat(), startPoint.y.toFloat(), endPoint.x.toFloat(), endPoint.y.toFloat(), linePaint)
        startPoint.x = endPoint.x
        startPoint.y = endPoint.y
        endPoint.x += screenWidth / 6
        endPoint.y = screenHeight / 6
        canvas.drawLine(startPoint.x.toFloat(), startPoint.y.toFloat(), endPoint.x.toFloat(), endPoint.y.toFloat(), linePaint)
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메인 엑티비티에서 커스텀뷰 그리기&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;package com.example.myapplication

import android.annotation.SuppressLint
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView

class MainActivity : AppCompatActivity() {
    @SuppressLint(&quot;MissingInflatedId&quot;)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val lineGraph = findViewById&amp;lt;CustomLineGraphView&amp;gt;(R.id.lineGraph)

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레이아웃에서 커스텀 뷰 표현&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&amp;gt;
&amp;lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;
    xmlns:tools=&quot;http://schemas.android.com/tools&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    tools:context=&quot;.MainActivity&quot;&amp;gt;

    &amp;lt;com.example.myapplication.CustomLineGraphView
        android:id=&quot;@+id/lineGraph&quot;
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;300dp&quot;
        app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
        app:layout_constraintEnd_toEndOf=&quot;parent&quot;
        app:layout_constraintStart_toStartOf=&quot;parent&quot;
        app:layout_constraintTop_toTopOf=&quot;parent&quot; /&amp;gt;

&amp;lt;/androidx.constraintlayout.widget.ConstraintLayout&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 위 코드 결과 화면입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 예제로 혹시 라이브러리를 사용하지 못하거나 혹은 사용하기엔 간단한 기능이라면 위와 같은 방법으로 간단하게 작성하는 것도 좋은 선택이라 생각합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;247&quot; data-origin-height=&quot;547&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7b0f7/btsz10qc507/cskHsymANCO779fhAm3kN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7b0f7/btsz10qc507/cskHsymANCO779fhAm3kN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7b0f7/btsz10qc507/cskHsymANCO779fhAm3kN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7b0f7%2Fbtsz10qc507%2FcskHsymANCO779fhAm3kN0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;247&quot; height=&quot;547&quot; data-origin-width=&quot;247&quot; data-origin-height=&quot;547&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Android</category>
      <author>hong0708</author>
      <guid isPermaLink="true">https://hong0708.tistory.com/32</guid>
      <comments>https://hong0708.tistory.com/entry/%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EC%97%86%EC%9D%B4-%EC%A7%81%EC%84%A0-%EA%B7%B8%EB%9E%98%ED%94%84-%EA%B7%B8%EB%A6%AC%EA%B8%B0#entry32comment</comments>
      <pubDate>Wed, 8 Nov 2023 10:59:32 +0900</pubDate>
    </item>
    <item>
      <title>백준 1717 집합의 표현 파이썬</title>
      <link>https://hong0708.tistory.com/entry/%EB%B0%B1%EC%A4%80-1717-%EC%A7%91%ED%95%A9%EC%9D%98-%ED%91%9C%ED%98%84-%ED%8C%8C%EC%9D%B4%EC%8D%AC</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1717&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.acmicpc.net/problem/1717&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1697099837259&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;1717번: 집합의 표현&quot; data-og-description=&quot;초기에 $n+1$개의 집합 $\{0\}, \{1\}, \{2\}, \dots , \{n\}$이 있다. 여기에 합집합 연산과, 두 원소가 같은 집합에 포함되어 있는지를 확인하는 연산을 수행하려고 한다. 집합을 표현하는 프로그램을 작&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/1717&quot; data-og-url=&quot;https://www.acmicpc.net/problem/1717&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dl4fS2/hyT9HMpeme/oTd6m4QGEjhCk4ByvwYnMK/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1717&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/1717&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dl4fS2/hyT9HMpeme/oTd6m4QGEjhCk4ByvwYnMK/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;1717번: 집합의 표현&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;초기에 $n+1$개의 집합 $\{0\}, \{1\}, \{2\}, \dots , \{n\}$이 있다. 여기에 합집합 연산과, 두 원소가 같은 집합에 포함되어 있는지를 확인하는 연산을 수행하려고 한다. 집합을 표현하는 프로그램을 작&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.acmicpc.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;합집합을 하는 연산과, 두 집합이 포함되어 있는지 판단하는 연산을 수행해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 두 연산을 통해 분리 집합을 활용해야 풀이가 가능하다는 것을 유추 할 수 있습니다. 분리 집합이란 노드를 합치고, 부모를 찾아 서로소 집합임을 판단 가능하기 때문에 각 연산 수행이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;find 함수를 통해 부모를 찾는 과정을 진행하고 union 함수를 통해 두 노드의 부모 노드를 합치는 연산을 수행하여 집합을 합칩니다. 아래는 위 알고리즘 예제 코드입니다.&lt;/p&gt;
&lt;pre class=&quot;python&quot; style=&quot;background-color: #2b2b2b; color: #a9b7c6;&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;# https://www.acmicpc.net/problem/1717

import sys

n, m = map(int, input().split())
parent = [i for i in range(n + 1)]


def find(x):
    while x != parent[x]:
        x = parent[x]
    return x


def union(x, y):
    if x &amp;lt; y:
        parent[y] = x
    else:
        parent[x] = y


for _ in range(m):
    k, a, b = map(int, sys.stdin.readline().split())
    if k == 0:
        x = find(a)
        y = find(b)
        union(x, y)
    else:
        if find(a) == find(b):
            print('YES')
        else:
            print('NO')&lt;/code&gt;&lt;/pre&gt;</description>
      <category>백준</category>
      <author>hong0708</author>
      <guid isPermaLink="true">https://hong0708.tistory.com/31</guid>
      <comments>https://hong0708.tistory.com/entry/%EB%B0%B1%EC%A4%80-1717-%EC%A7%91%ED%95%A9%EC%9D%98-%ED%91%9C%ED%98%84-%ED%8C%8C%EC%9D%B4%EC%8D%AC#entry31comment</comments>
      <pubDate>Thu, 12 Oct 2023 18:01:32 +0900</pubDate>
    </item>
    <item>
      <title>분리 집합(Union-Find) 파이썬(Python)</title>
      <link>https://hong0708.tistory.com/entry/%EB%B6%84%EB%A6%AC-%EC%A7%91%ED%95%A9Union-Find-%ED%8C%8C%EC%9D%B4%EC%8D%ACPython</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Union-Find&lt;/b&gt;는 &lt;b&gt;트리구조&lt;/b&gt;를 활용해 노드를 합치고 부모를 찾아서 이를 통해 서로소 집합을 찾아내는 알고리즘입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;find&lt;/b&gt; 함수를 통해 부모 노드를 찾을 때 까지 재귀를 활용하여 호출합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때, 재귀적으로 호출 하면 파이썬의 경우 문제가 생기는 경우가 있는데 이에 대한 내용은 하단에 새로운 코드를 추가하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;union&lt;/b&gt; 함수는 두 노드의 부모노드를 찾고 이를 합치는데 이때 노드의 번호에 따라 합칠 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 함수를 수행하기 위해선 해당 노드의 &lt;b&gt;부모노드를 저장하는 리스트&lt;/b&gt;를 가지고 있어야합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 위 함수들과 알고리즘을 구현한 예제 코드입니다.&lt;/p&gt;
&lt;pre class=&quot;python&quot; style=&quot;background-color: #2b2b2b; color: #a9b7c6;&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;n, m = map(int, input().split())
parent = [i for i in range(n)]

def find(x):
    if parent[x] != x:
        parent[x] = find(parent[x])
    return parent[x]


def union(x, y):
    if x &amp;lt; y:
        parent[y] = x
    else:
        parent[x] = y
        

for _ in range(m):
    k, a, b = map(int, sys.stdin.readline().split())
    if k == 0:
        x = find(a)
        y = find(b)
        union(x, y)
        
    else:
        if find(a) == find(b):
            print('YES')
        else:
            print('NO')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 find 함수를 while문을 통해 수정한 코드입니다.&lt;/p&gt;
&lt;pre class=&quot;python&quot; style=&quot;background-color: #2b2b2b; color: #a9b7c6;&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;def find(x):
    while x != parent[x]:
        x = parent[x]
    return x&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Algorithm</category>
      <author>hong0708</author>
      <guid isPermaLink="true">https://hong0708.tistory.com/30</guid>
      <comments>https://hong0708.tistory.com/entry/%EB%B6%84%EB%A6%AC-%EC%A7%91%ED%95%A9Union-Find-%ED%8C%8C%EC%9D%B4%EC%8D%ACPython#entry30comment</comments>
      <pubDate>Thu, 12 Oct 2023 17:27:55 +0900</pubDate>
    </item>
    <item>
      <title>백준 2623 음악프로그램 파이썬</title>
      <link>https://hong0708.tistory.com/entry/%EB%B0%B1%EC%A4%80-2623-%EC%9D%8C%EC%95%85%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%ED%8C%8C%EC%9D%B4%EC%8D%AC</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/2623&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.acmicpc.net/problem/2623&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1696914585719&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;2623번: 음악프로그램&quot; data-og-description=&quot;첫째 줄에는 가수의 수 N과 보조 PD의 수 M이 주어진다. 가수는&amp;nbsp;번호 1, 2,&amp;hellip;,N 으로 표시한다. 둘째 줄부터 각 보조 PD가 정한 순서들이 한 줄에 하나씩 나온다. 각 줄의 맨 앞에는 보조 PD가 담당한 &quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/2623&quot; data-og-url=&quot;https://www.acmicpc.net/problem/2623&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/N7V1V/hyT9KhqpWV/yrIk6r3GKrZ8KoNkG8KSPk/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/2623&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/2623&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/N7V1V/hyT9KhqpWV/yrIk6r3GKrZ8KoNkG8KSPk/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;2623번: 음악프로그램&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;첫째 줄에는 가수의 수 N과 보조 PD의 수 M이 주어진다. 가수는&amp;nbsp;번호 1, 2,&amp;hellip;,N 으로 표시한다. 둘째 줄부터 각 보조 PD가 정한 순서들이 한 줄에 하나씩 나온다. 각 줄의 맨 앞에는 보조 PD가 담당한&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.acmicpc.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n 팀의 가수들의 순서를 모든 조건에 만족시켜 정렬을 하는 문제입니다. 이때, 보조PD들이 해당 정렬에 대한 &lt;b&gt;우선 순위&lt;/b&gt; 즉, &lt;b&gt;방향성을 제공&lt;/b&gt;해주고 이를 만족시켜 정렬을 해야합니다. 이부분을 활용하면&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt; 위상 정렬&lt;/b&gt;&lt;/span&gt;을 통해 해답을 도출하면 쉽게 풀이가 가능하다는 점을 추론할 수 있습니다. 뿐만 아니라 위상 정렬을 진행 할 때 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;큐가 비었지만 모든 노드를 방문하지 않았을 경우 이는 사이클이 존재한다는 것&lt;/span&gt;&lt;/b&gt;을 알 수 있어 정렬이 불가능한 점을 확인 할 수 있으니 이를 활용해 문제 조건에 따라 0을 출력하면 해결이 가능합니다. 위상 정렬은 알고리즘 탭에 정리를 해두었으니 이를 참고하시면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 보조PD가 제공하는 우선순위를 입력받아 진입차수를 측정해줍니다. 이후 진입 차수가 0인 가수들을 먼저 큐에 추가하고 해당 가수 다음으로 나와야할 가수들의 진입차수를 -1 해주며 다시 진입차수가 0이 된 가수들을 큐에 추가해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 위 알고리즘의 예제 코드입니다.&lt;/p&gt;
&lt;pre class=&quot;vim&quot; style=&quot;background-color: #2b2b2b; color: #a9b7c6;&quot;&gt;&lt;code&gt;# https://www.acmicpc.net/problem/2623

import sys
from collections import deque

n, m = map(int, input().split())
arr = [0 for _ in range(n + 1)]
r = [[] for _ in range(n + 1)]
ans = []

for _ in range(m):
    impl = list(map(int, sys.stdin.readline().split()))
    dg = 1
    for i in range(2, len(impl)):
        arr[impl[i]] += 1
        dg += 1
        r[impl[i - 1]].append(impl[i])

dq = deque()
for i in range(1, n + 1):
    if arr[i] == 0:
        dq.append(i)

while dq:
    now = dq.popleft()
    ans.append(now)
    for i in r[now]:
        arr[i] -= 1
        if arr[i] == 0:
            dq.append(i)
if len(ans) == n:
    for i in ans:
        print(i)
else:
    print(0)
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>백준</category>
      <author>hong0708</author>
      <guid isPermaLink="true">https://hong0708.tistory.com/29</guid>
      <comments>https://hong0708.tistory.com/entry/%EB%B0%B1%EC%A4%80-2623-%EC%9D%8C%EC%95%85%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%ED%8C%8C%EC%9D%B4%EC%8D%AC#entry29comment</comments>
      <pubDate>Tue, 10 Oct 2023 14:15:15 +0900</pubDate>
    </item>
    <item>
      <title>위상 정렬(Topology Sort) 파이썬(Python)</title>
      <link>https://hong0708.tistory.com/entry/%EC%9C%84%EC%83%81-%EC%A0%95%EB%A0%ACTopology-Sort-%ED%8C%8C%EC%9D%B4%EC%8D%ACPython</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;위상 정렬이란 순환(사이클)이 없는 방향 그래프의 모든 노드를 방향성에 위배 하지 않고 나열하는 정렬 알고리즘 입니다. 여기서 알 수 있는 점이 1. &lt;b&gt;순환이 없다&lt;/b&gt; 2. &lt;b&gt;방향성 즉 우선순위를 판단하여 정렬한다&lt;/b&gt; 두점을 알 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&amp;nbsp;그래프 내부에 사이클이 없다&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt; 방향성을 가진 간선으로 이뤄진 그래프이다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 점을 봐서 DAG(Direct Acyclic Graph)에서 실행 될 수 있다고 할 수 있습니다. 이 때 문제에서 방향성을 우선순위 즉, 어떠한 테스크에 대해 먼저 선행되어야 할 다른 테스크가 있을 때 활용된다고 생각하고 풀이를 진행하면 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;위상 정렬 알고리즘&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;큐를 활용하여 &lt;b&gt;진입 차수가 0&lt;/b&gt;인 노드를 지속적으로 추가합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;진입 차수를 측정합니다. 진입 차수는 특정 노드로 들어오는 간선의 수로 특정 테스크 이전에 수행되는 테스크의 수입니다.&lt;/li&gt;
&lt;li&gt;진입 차수가 0 인 노드를 큐에 추가합니다.&lt;/li&gt;
&lt;li&gt;큐에서 원소를 빼 해당 원소가 연결되는 다른 노드들의 간선을 제거합니다. 즉, 진입 차수를 -1 해줍니다.&lt;/li&gt;
&lt;li&gt;만약 진입차수가 0이 된다면 해당 노드들을 큐에 다시 추가합니다.&lt;/li&gt;
&lt;li&gt;위 과정을 큐가 빌 때 까지 반복합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 중요한 점은 노드가 큐에 들어오는 순서가 정렬 순서로 결과를 저장해야하며, 만약 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;모든 노드를 방문 하지 않았는데 큐가 비어버리면 이는 사이클이 존재하는 것으로 정렬이 불가능&lt;/b&gt;&lt;/span&gt;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 위 알고리즘 예제 코드입니다.&lt;/p&gt;
&lt;pre class=&quot;vim&quot; style=&quot;background-color: #2b2b2b; color: #a9b7c6;&quot;&gt;&lt;code&gt;import sys
from collections import deque

n, m = map(int, input().split())
arr = [0 for _ in range(n + 1)]
r = [[] for _ in range(n + 1)]
ans = []

for _ in range(m):
    impl = list(map(int, sys.stdin.readline().split()))
    dg = 1
    for i in range(2, len(impl)):
        arr[impl[i]] += 1
        dg += 1
        r[impl[i - 1]].append(impl[i])

dq = deque()
for i in range(1, n + 1):
    if arr[i] == 0:
        dq.append(i)

while dq:
    now = dq.popleft()
    ans.append(now)
    for i in r[now]:
        arr[i] -= 1
        if arr[i] == 0:
            dq.append(i)
if len(ans) == n:
    for i in ans:
        print(i)
else:
    print(0)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드는 아래 문제의 해답 코드로 위상 정렬을 활용한 문제입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/2623&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.acmicpc.net/problem/2623&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1696914562230&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;2623번: 음악프로그램&quot; data-og-description=&quot;첫째 줄에는 가수의 수 N과 보조 PD의 수 M이 주어진다. 가수는&amp;nbsp;번호 1, 2,&amp;hellip;,N 으로 표시한다. 둘째 줄부터 각 보조 PD가 정한 순서들이 한 줄에 하나씩 나온다. 각 줄의 맨 앞에는 보조 PD가 담당한 &quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/2623&quot; data-og-url=&quot;https://www.acmicpc.net/problem/2623&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/N7V1V/hyT9KhqpWV/yrIk6r3GKrZ8KoNkG8KSPk/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/2623&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/2623&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/N7V1V/hyT9KhqpWV/yrIk6r3GKrZ8KoNkG8KSPk/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;2623번: 음악프로그램&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;첫째 줄에는 가수의 수 N과 보조 PD의 수 M이 주어진다. 가수는&amp;nbsp;번호 1, 2,&amp;hellip;,N 으로 표시한다. 둘째 줄부터 각 보조 PD가 정한 순서들이 한 줄에 하나씩 나온다. 각 줄의 맨 앞에는 보조 PD가 담당한&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.acmicpc.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm</category>
      <author>hong0708</author>
      <guid isPermaLink="true">https://hong0708.tistory.com/28</guid>
      <comments>https://hong0708.tistory.com/entry/%EC%9C%84%EC%83%81-%EC%A0%95%EB%A0%ACTopology-Sort-%ED%8C%8C%EC%9D%B4%EC%8D%ACPython#entry28comment</comments>
      <pubDate>Tue, 10 Oct 2023 14:09:22 +0900</pubDate>
    </item>
    <item>
      <title>백준 1005 ACM Craft 파이썬</title>
      <link>https://hong0708.tistory.com/entry/%EB%B0%B1%EC%A4%80-1005-ACM-Craft-%ED%8C%8C%EC%9D%B4%EC%8D%AC</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1005&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.acmicpc.net/problem/1005&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1696606936228&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;1005번: ACM Craft&quot; data-og-description=&quot;첫째 줄에는 테스트케이스의 개수 T가 주어진다. 각 테스트 케이스는 다음과 같이 주어진다.&amp;nbsp;첫째 줄에 건물의 개수 N과 건물간의 건설순서 규칙의 총 개수 K이 주어진다.&amp;nbsp;(건물의 번호는 1번부&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/1005&quot; data-og-url=&quot;https://www.acmicpc.net/problem/1005&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/QX64q/hyT9BqhEWY/AiQDJUdpWCjw28ojTLogD1/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1005&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/1005&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/QX64q/hyT9BqhEWY/AiQDJUdpWCjw28ojTLogD1/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;1005번: ACM Craft&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;첫째 줄에는 테스트케이스의 개수 T가 주어진다. 각 테스트 케이스는 다음과 같이 주어진다.&amp;nbsp;첫째 줄에 건물의 개수 N과 건물간의 건설순서 규칙의 총 개수 K이 주어진다.&amp;nbsp;(건물의 번호는 1번부&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.acmicpc.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;건물이 지어지는 우선순위가 있고 최종적 목표 건물이 지어질 때 까지 시간을 구해야 합니다. 이때 건물을 짓는 &lt;b&gt;우선순위&lt;/b&gt;가 존재하는 것을 토대로 &lt;b&gt;위상정렬&lt;/b&gt; 아이디어를 떠올릴 수 있습니다. 어떤 건물이 지어질 때 이전에 먼저 건물을 지어야하는 즉 &lt;b&gt;진입 차수&lt;/b&gt;에 대한 내용임을 짐작 할 수 있으니 이를 활용해 풀이를 진행하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;먼저 입력을 받으며 해당 건물의 진입 차수를 측정하고 이후 &lt;b&gt;진입차수가 0인 건물부터 큐에 추가&lt;/b&gt;해주면 됩니다. 이때 다음 건물이 지어지는 시간을 측정 할 때 &lt;b&gt;기존의 결과를 저장&lt;/b&gt;을 하며 현재 &lt;b&gt;큐에서 나온 건물이 지어지는 시간 + 다음 건물이 지어지는 시간을 더한 값&lt;/b&gt;과 기존의 결과 시간을 비교하여 더 큰값으로 갱신을 통해 풀이하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;아래는 해당 알고리즘 예제 코드입니다.&lt;/p&gt;
&lt;pre class=&quot;vim&quot; style=&quot;background-color: #2b2b2b; color: #a9b7c6;&quot;&gt;&lt;code&gt;# https://www.acmicpc.net/problem/1005

import sys
from collections import deque

for _ in range(int(input())):
    n, k = map(int, input().split())
    cost = [0] + list(map(int, sys.stdin.readline().split()))
    degree = [0 for _ in range(n + 1)]
    route = [[] for _ in range(n + 1)]
    res = [0 for _ in range(n + 1)]

    for _ in range(k):
        s, e = map(int, input().split())
        route[s].append(e)
        degree[e] += 1
    des = int(input())

    dq = deque()
    for i in range(1, n + 1):
        if degree[i] == 0:
            dq.append(i)
            res[i] = cost[i]

    while dq:
        now = dq.popleft()
        for next in route[now]:
            degree[next] -= 1
            res[next] = max(res[next], res[now] + cost[next])
            if degree[next] == 0:
                dq.append(next)

    print(res[des])
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>백준</category>
      <author>hong0708</author>
      <guid isPermaLink="true">https://hong0708.tistory.com/27</guid>
      <comments>https://hong0708.tistory.com/entry/%EB%B0%B1%EC%A4%80-1005-ACM-Craft-%ED%8C%8C%EC%9D%B4%EC%8D%AC#entry27comment</comments>
      <pubDate>Sat, 7 Oct 2023 01:25:08 +0900</pubDate>
    </item>
    <item>
      <title>백준 2252 줄 세우기 파이썬</title>
      <link>https://hong0708.tistory.com/entry/%EB%B0%B1%EC%A4%80-2252-%EC%A4%84-%EC%84%B8%EC%9A%B0%EA%B8%B0-%ED%8C%8C%EC%9D%B4%EC%8D%AC</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/2252&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.acmicpc.net/problem/2252&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1696578866261&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;2252번: 줄 세우기&quot; data-og-description=&quot;첫째 줄에 N(1 &amp;le; N &amp;le; 32,000), M(1 &amp;le; M &amp;le; 100,000)이 주어진다. M은 키를 비교한 회수이다. 다음 M개의 줄에는 키를 비교한 두 학생의 번호 A, B가 주어진다. 이는 학생 A가 학생 B의 앞에 서야 한다는 의&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/2252&quot; data-og-url=&quot;https://www.acmicpc.net/problem/2252&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cKDkv4/hyT9K8wnHw/5zs1v0woMaGzQ7Uy6NeXIk/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/2252&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/2252&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cKDkv4/hyT9K8wnHw/5zs1v0woMaGzQ7Uy6NeXIk/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;2252번: 줄 세우기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;첫째 줄에 N(1 &amp;le; N &amp;le; 32,000), M(1 &amp;le; M &amp;le; 100,000)이 주어진다. M은 키를 비교한 회수이다. 다음 M개의 줄에는 키를 비교한 두 학생의 번호 A, B가 주어진다. 이는 학생 A가 학생 B의 앞에 서야 한다는 의&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.acmicpc.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학생들을 키에 따른 줄을 세워야하는 문제입니다. 하지만 각 학생들의 정확한 키가 아닌 크기 비교에 따른 기준만 있습니다. 이에 따라 기준에만 만족하기 때문에 여러 답이 나올 수 있습니다. 이렇게 비교한 결과에 따라 정렬을 할 때 활용 가능한 것이 &lt;b&gt;위상정렬&lt;/b&gt;입니다. 위상정렬에 관해선 알고리즘을 따로 후에 다뤄보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 각 학생들의 키 비교 입력을 통해 학생들의 &lt;b&gt;진입 차수&lt;/b&gt;를 계산합니다. 이후 먼저 진입 차수가 0인 학생들을 큐에 넣고 정렬하며 해당 학생들보다 뒤에 서야하는 학생들의 차수를 &lt;b&gt;-1&lt;/b&gt; 해주며 항상 &lt;b&gt;진입 차수가 0인 학생&lt;/b&gt;을 정답에 정렬해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진입 차수가 0일 때 정렬하는 이유는 진입 차수가 해당 학생 앞에 서야 하는 학생들의 수를 의미하기 때문에 앞에 더 이상 서야하는 학생이 없다고 판단 할 때 까지 정렬하지 않은 것 입니다. 아래는 해당 알고리즘 예제 코드입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;vim&quot; style=&quot;background-color: #2b2b2b; color: #a9b7c6;&quot;&gt;&lt;code&gt;# https://www.acmicpc.net/problem/2252

from collections import deque

n, m = map(int, input().split())
line = [0 for _ in range(n + 1)]
arr1 = [[] for _ in range(n + 1)]
ans = []
for _ in range(m):
    s, e = map(int, input().split())
    arr1[s].append(e)
    line[e] += 1

dq = deque()

for i in range(1, n + 1):
    if line[i] == 0:
        dq.append(i)
while dq:
    now = dq.popleft()
    ans.append(now)
    for i in arr1[now]:
        line[i] -= 1
        if line[i] == 0:
            dq.append(i)
print(*ans)
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>백준</category>
      <author>hong0708</author>
      <guid isPermaLink="true">https://hong0708.tistory.com/26</guid>
      <comments>https://hong0708.tistory.com/entry/%EB%B0%B1%EC%A4%80-2252-%EC%A4%84-%EC%84%B8%EC%9A%B0%EA%B8%B0-%ED%8C%8C%EC%9D%B4%EC%8D%AC#entry26comment</comments>
      <pubDate>Fri, 6 Oct 2023 17:54:02 +0900</pubDate>
    </item>
    <item>
      <title>Fragment lifecycle</title>
      <link>https://hong0708.tistory.com/entry/Fragment-lifecycle</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;Fragment의 생명주기&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;708&quot; data-origin-height=&quot;860&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkDEX2/btsxkDkPx9c/ugY0cPGYxVwG2grn1q8ql1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkDEX2/btsxkDkPx9c/ugY0cPGYxVwG2grn1q8ql1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkDEX2/btsxkDkPx9c/ugY0cPGYxVwG2grn1q8ql1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkDEX2%2FbtsxkDkPx9c%2FugY0cPGYxVwG2grn1q8ql1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;708&quot; height=&quot;860&quot; data-origin-width=&quot;708&quot; data-origin-height=&quot;860&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. onAttach()&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Fragment가 Activity에 붙을 때 호출됩니다. Fragment 가 FragmentManager에 추가되며 Fragment의 생명주기를 관리합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. onCreate()&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프래그먼트가 생성될 때 호출됩니다. 프래그먼트가 일시정지되거나 중단되었다가 재개되었을 때 유지하고자 하는 것을 초기화해야 합니다. Bunndlle로 데이터가 넘어오고 Fragment만 Created 된 상황입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;UI 초기화는 불가능&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. onCreateView()&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Fragment가 View를 그립니다. 즉, Layout을 Inflate하는 작업을 수행하는 부분으로 View를 반환합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;savedInstanceState로 이전 상태에 대한 데이터 제공을 받습니다.&lt;/li&gt;
&lt;li&gt;View와 관련된 객체를 초기화 할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. onViewCreated()&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;onCreateView()를 통해 반환된 &lt;b&gt;View 객체는 onViewCreated()의 파라미터로 전달&lt;/b&gt;됩니다. 즉 View의 초기값 설정이 가능하고 &lt;b&gt;LiveData 옵저빙, RecyclerView, ViewPager2에 사용될 Adapter 세팅&lt;/b&gt;을 해주는 것이 적합 합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 때 Lifecycle이 &lt;b&gt;INITIALIZED 상태로 업데이트&lt;/b&gt;가 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. onViewStateRestored()&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저장해둔 모든 state 값이 Fragment의 View의 계층 구조에 복원되었을 때 호출됩니다. ex) 체크박스 위젯이 현재 체크되어있는가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;View Lifecycle Owner는 이때 INITIALIZED상태에서 CREATED 상태로 변경됨을 알립니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. onStart()&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 부터 Fragment가 사용자에게 보여질 수 있습니다. Activity의 onStart()와 유사하며 childFragmentManager을 통해 FragmentTransaction을 사용할 수 있습니다. View Lifecycle Owner는 이때 CREATED 상태에서 STARTED로 상태 변경됨을 알립니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;7. onResume()&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자와 Fragment가 상호작용 할 수 있는 상태입니다. 이때, 모든 Animator, Transition은 종료되어 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;8. onPause()&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Fragment가 떠나는 중이지만 아직 visible 입니다. 이때 View의 lifecycle은 PAUSED가 아닌 STARTED입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;9. onStop()&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Fragment가 더 이상 화면에 보여지지 않는 Invisible 상태입니다. 이때, 실행할 필요가 없는 기능들을 정지할 수 있고 또한, 보이지 않는 동안에 필요없는 리소스들을 해제 및 조정하여 최적화를 진행 해야합니다. (ex. 디비 저장)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;API 28버전을 기점으로 onSaveInstanceState() 함수와 onStop() 함수 호출 순서가 달라짐, 따라서 &lt;b&gt;onStop()이 FragmentTransaction을 안전하게 수행하는 마지막 지점입니다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;10. onDestoryView()&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 exit animation, transaction이 완료되고 Fragment가 화면으로부터 벗어났을 경우 호출됩니다. View Lifecycle Owner는 이때 &lt;b&gt;CREATED&lt;/b&gt; 상태에서 &lt;b&gt;DESTROYED&lt;/b&gt;상태로 변경됨을 알립니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가비지 컬렉터에 의해 수거될 수 있도록 &lt;b&gt;Fragment View에 대한 모든 참조가 제거되어야 합니다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;getViewLifecycleOwnerLiveData()&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;11. onDestroy()&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Activity 와 Fragment가 소멸되기 전에 호출됩니다. 화면모드가 바뀔 때 또한 동일합니다.(가로 세로 모드)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;12. onDetach()&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;프래그먼트가 액티비티로부터 해제되어질 때 호출된다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.android.com/guide/components/fragments?hl=ko&quot;&gt;https://developer.android.com/guide/components/fragments?hl=ko&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1696572747911&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프래그먼트 &amp;nbsp;|&amp;nbsp; Android 개발자 &amp;nbsp;|&amp;nbsp; Android Developers&quot; data-og-description=&quot;A Fragment represents a behavior or a portion of user interface in an Activity. You can combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities. You can think of a fragment as a modular section&quot; data-og-host=&quot;developer.android.com&quot; data-og-source-url=&quot;https://developer.android.com/guide/components/fragments?hl=ko&quot; data-og-url=&quot;https://developer.android.com/guide/components/fragments?hl=ko&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/rb9Jk/hyT5RBqPoB/OCHuaSvY9dNGtufYThzkSk/img.png?width=317&amp;amp;height=847&amp;amp;face=0_0_317_847,https://scrap.kakaocdn.net/dn/cq64he/hyT5ZlXuOw/YPknGVCzgjzuPenz47Rth1/img.png?width=340&amp;amp;height=675&amp;amp;face=0_0_340_675&quot;&gt;&lt;a href=&quot;https://developer.android.com/guide/components/fragments?hl=ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.android.com/guide/components/fragments?hl=ko&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/rb9Jk/hyT5RBqPoB/OCHuaSvY9dNGtufYThzkSk/img.png?width=317&amp;amp;height=847&amp;amp;face=0_0_317_847,https://scrap.kakaocdn.net/dn/cq64he/hyT5ZlXuOw/YPknGVCzgjzuPenz47Rth1/img.png?width=340&amp;amp;height=675&amp;amp;face=0_0_340_675');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프래그먼트 &amp;nbsp;|&amp;nbsp; Android 개발자 &amp;nbsp;|&amp;nbsp; Android Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A Fragment represents a behavior or a portion of user interface in an Activity. You can combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities. You can think of a fragment as a modular section&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.android.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Android</category>
      <author>hong0708</author>
      <guid isPermaLink="true">https://hong0708.tistory.com/25</guid>
      <comments>https://hong0708.tistory.com/entry/Fragment-lifecycle#entry25comment</comments>
      <pubDate>Fri, 6 Oct 2023 15:13:20 +0900</pubDate>
    </item>
    <item>
      <title>Activity LifeCycle</title>
      <link>https://hong0708.tistory.com/entry/Activity-LifeCycle</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;Activity 의 생명주기(LifeCycle)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생명주기는 액티비티가 시작하고 끝날 때까지의 과정으로 상태변화에 따라 콜백 메서드를 통합하여 명칭합니다. 이에 따라 메서드를 통해 생태 변화를 인지할 수 있고 이에 따른 대응과 문제 발생 시점 파악이 가능합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;460&quot; data-origin-height=&quot;567&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c6s1rX/btsv8effVAJ/D3SYXSLGqkzLDSCR6EKtT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c6s1rX/btsv8effVAJ/D3SYXSLGqkzLDSCR6EKtT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c6s1rX/btsv8effVAJ/D3SYXSLGqkzLDSCR6EKtT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc6s1rX%2Fbtsv8effVAJ%2FD3SYXSLGqkzLDSCR6EKtT1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;460&quot; height=&quot;567&quot; data-origin-width=&quot;460&quot; data-origin-height=&quot;567&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;onCreate()&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최초로 액티비티 실행하면 &lt;b&gt;onCreate()&lt;/b&gt; 호출되는데 초기화 관련 작업을 진행하면 좋습니다. Activity가 시작 될 때 한번만 실행되는 메소드로 데이터를 목록에 &lt;b&gt;바인딩&lt;/b&gt;하고, 활동을 &lt;b&gt;ViewModel&lt;/b&gt;과 연결등의 작업이 적합합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;onStart()&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 onStart()가 호출되는데 사용자가 액티비티를 보기 전 호출되기 때문에 &lt;b&gt;진입할 때마다 실행 시켜야하는 코드&lt;/b&gt;를 작성하기 적합합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;onResume()&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;액티비티가 사용자와 상호작용이 가능한 포그라운드에 위치하면 onResume()호출됩니다. 이 상태를 액티비티가 실행 중인 것으로 보며 화면상에 보이기 시작합니다. 다른 화면에서 돌아오는 경우에도 onResume()가 호출되니 갱신에 관한 작업을 진행하기 적합합니다. 하지만 이 때 수행시간이 길어지면 화면의 버벅임이 유발 될 수 있기 때문에 유의해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;onPause()&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반대로 상호작용이 불가능한 상태, 즉 포커스를 잃은 상태가 되면 onPause()가 호출됩니다. 방해되는 이벤트가 발생하고 Activity의 일부는 보이지만 다른 Activity가 foreground로 나올 때 호출되는데 매우 잠깐 실행됩니다. 때문에 해당 메소드에서 작업시간이 긴 무거운 작업은 부적합합니다. (ex. 데이터를 저장하거나, 네트워크를 호출) 또, 현재 상태에서 기기의 메모리 부족으로 앱의 프로세스가 강제로 종료될 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;onStop()&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;onStop()은 액티비타가 더 이상 보이지 않을 때 호출됩니다. 또 onPause()에서 실행하지 못한 무거운 작업을 진행하기 적합합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;onRestart()&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;onRestart()는 다른 Activity에서 또는 홈에서 다시 돌아오는 경우 호출됩니다. 이후 onStart()를 통해 화면이 돌아옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;onDestroy()&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;액티비티가 종료되거나 앱프로세스 자체가 종료되면 onDestroy()가 호출된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;특이사항&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;불투명한 액티비티가 최상단으로 올라와 기존의 액티비티가 완전히 보이지 않게 되면 onPause() onStop()까지 바로 호출되지만 투명한 액티비티가 실행된다면(액티비티의 스타일 속성이 투명하다고 선언만 되어 있어도 투명 액티비티로 간주) onPause()까지 호출됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 다이얼로그를 띄운다면 onPause()가 호출되어야 할 것 같지만 다이얼로그는 액티비티의 일부이기 때문에 아무런 함수가 호출되지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.android.com/guide/components/activities/activity-lifecycle?hl=ko&quot;&gt;https://developer.android.com/guide/components/activities/activity-lifecycle?hl=ko&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Android</category>
      <author>hong0708</author>
      <guid isPermaLink="true">https://hong0708.tistory.com/24</guid>
      <comments>https://hong0708.tistory.com/entry/Activity-LifeCycle#entry24comment</comments>
      <pubDate>Wed, 27 Sep 2023 17:24:43 +0900</pubDate>
    </item>
  </channel>
</rss>