<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>정화 코딩</title>
    <link>https://jungh150c.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Tue, 21 Jul 2026 21:46:06 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>jungh150c</managingEditor>
    <image>
      <title>정화 코딩</title>
      <url>https://tistory1.daumcdn.net/tistory/5525681/attach/d5609493964c488b89bdf315c9f4c349</url>
      <link>https://jungh150c.tistory.com</link>
    </image>
    <item>
      <title>[C++] 상어의 저녁식사 (백준 1671번)</title>
      <link>https://jungh150c.tistory.com/327</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1158&quot; data-origin-height=&quot;508&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7emUm/dJMb99SJT6Z/mZlCYMm1Ukni0q10M3rIf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7emUm/dJMb99SJT6Z/mZlCYMm1Ukni0q10M3rIf0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7emUm/dJMb99SJT6Z/mZlCYMm1Ukni0q10M3rIf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7emUm%2FdJMb99SJT6Z%2FmZlCYMm1Ukni0q10M3rIf0%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;1158&quot; height=&quot;508&quot; data-origin-width=&quot;1158&quot; data-origin-height=&quot;508&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1671&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1671&lt;/a&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;일단 한 상어가 최대 두 개의 상어만 먹을 수 있다고 했으니, 왼쪽 그룹에는 상어 하나 당 두 개의 노드를 두고 (총 2 * n개) 오른쪽 그룹에는 상어 하나 당 하나의 노드를 둔 다음 (총 n개), 먹을 수 있는 관계인 경우에 연결해주면 될 것 같다.&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;참고로, &quot;이미 잡아먹힌 상어는 다른 상어들을 잡아먹을 수 없다&quot;는 조건은 크게 신경 쓸 필요가 없다. 매칭 결과를 보고 먹히는 쪽부터 실행한다고 생각할 수 있다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 이를 처리하기 위해서 전부 동일한 쌍의 경우에는, 번호가 작은 상어가 잡아먹을 수 있다고 임의로 정해두고 간선을 연결하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1769499809755&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Reference: green55 teamnote
// https://github.com/green5555/Teamnote/blob/master/TeamNote/BiMatch.cpp

#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;

const int MAX = 151;
struct BiMatching {
    vector&amp;lt;int&amp;gt; adj[MAX+5];
    int iter, A[MAX+5], B[MAX+5], was[MAX+5];

    bool dfs(int u) {
        was[u] = iter;
        for (int v : adj[u]) {
            if (B[v] == -1) {
                A[u] = v;
                B[v] = u;
                return true;
            }
        }
        for (int v : adj[u]) {
            if (was[B[v]] != iter &amp;amp;&amp;amp; dfs(B[v])) {
                A[u] = v;
                B[v] = u;
                return true;
            }
        }
        return false;
    }

    int biMatch(int n=MAX) {
        fill(A, A+n, -1);
        fill(B, B+n, -1);
        fill(was, was+n, 0);
        iter = 0;
        int res = 0;
        while (true) {
            iter++;
            int add = 0;
            for (int i = 0; i &amp;lt; n; i++) {
                if (A[i] == -1 &amp;amp;&amp;amp; dfs(i)) {
                    add++;
                }
            }
            if (add == 0) {
                break;
            }
            res += add;
        }
        return res;
    }
};

void solve() {
    BiMatching bm;

    int n;
    cin &amp;gt;&amp;gt; n;

    vector&amp;lt;int&amp;gt; a(n);
    vector&amp;lt;int&amp;gt; b(n);
    vector&amp;lt;int&amp;gt; c(n);
    for (int i = 0; i &amp;lt; n; i++) cin &amp;gt;&amp;gt; a[i] &amp;gt;&amp;gt; b[i] &amp;gt;&amp;gt; c[i];

    for (int i = 0; i &amp;lt; n; i++) {
        for (int j = 0; j &amp;lt; n; j++) {
            if (i == j) continue;
            if (a[i] == a[j] &amp;amp;&amp;amp; b[i] == b[j] &amp;amp;&amp;amp; c[i] == c[j]) {
                if (i &amp;lt; j) {
                    bm.adj[i].push_back(j + 100);
                    bm.adj[i + 50].push_back(j + 100);
                }
            } else if (a[i] &amp;gt;= a[j] &amp;amp;&amp;amp; b[i] &amp;gt;= b[j] &amp;amp;&amp;amp; c[i] &amp;gt;= c[j]) {
                bm.adj[i].push_back(j + 100);
                bm.adj[i + 50].push_back(j + 100);
            }
        }
    }

    cout &amp;lt;&amp;lt; n - bm.biMatch() &amp;lt;&amp;lt; '\n';
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int T = 1;
    for (int i = 0; i &amp;lt; T; i++) {
        solve();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(AC)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>PS</category>
      <category>C++</category>
      <category>이분 매칭</category>
      <author>jungh150c</author>
      <guid isPermaLink="true">https://jungh150c.tistory.com/327</guid>
      <comments>https://jungh150c.tistory.com/327#entry327comment</comments>
      <pubDate>Tue, 27 Jan 2026 16:43:40 +0900</pubDate>
    </item>
    <item>
      <title>뉴비의 2025 ICPC Seoul Regional 예선 후기</title>
      <link>https://jungh150c.tistory.com/325</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;서론&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음이자 마지막으로 나가는 ICPC이다. 졸업하기도 하고 나이도 그렇고 올해가 마지막 기회다.&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;PS를 시작한 건 최근은 아니지만 열심히 하기 시작한 게 최근이라서 뉴비라고 적었다. 1년도 안 된 것 같다. 사실 딱히 열심히도 아닌 것 같기도... 하핫&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2025&quot; data-origin-height=&quot;503&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUpp92/dJMcagD0hWm/WRSVKaTMEJtukIBGrjkGtK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUpp92/dJMcagD0hWm/WRSVKaTMEJtukIBGrjkGtK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUpp92/dJMcagD0hWm/WRSVKaTMEJtukIBGrjkGtK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUpp92%2FdJMcagD0hWm%2FWRSVKaTMEJtukIBGrjkGtK%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;2025&quot; height=&quot;503&quot; data-origin-width=&quot;2025&quot; data-origin-height=&quot;503&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2031&quot; data-origin-height=&quot;498&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmvRD9/dJMcafkMnYX/xK2TvYkRIf606bPwVcKVG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmvRD9/dJMcafkMnYX/xK2TvYkRIf606bPwVcKVG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmvRD9/dJMcafkMnYX/xK2TvYkRIf606bPwVcKVG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmvRD9%2FdJMcafkMnYX%2FxK2TvYkRIf606bPwVcKVG0%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;2031&quot; height=&quot;498&quot; data-origin-width=&quot;2031&quot; data-origin-height=&quot;498&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2035&quot; data-origin-height=&quot;497&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cVm0Zc/dJMcabbB2SZ/wizMKNKaPXCIUVPWOUkGxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cVm0Zc/dJMcabbB2SZ/wizMKNKaPXCIUVPWOUkGxK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cVm0Zc/dJMcabbB2SZ/wizMKNKaPXCIUVPWOUkGxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcVm0Zc%2FdJMcabbB2SZ%2FwizMKNKaPXCIUVPWOUkGxK%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;2035&quot; height=&quot;497&quot; data-origin-width=&quot;2035&quot; data-origin-height=&quot;497&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2026&quot; data-origin-height=&quot;499&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c4uQA1/dJMcaa4P2KJ/WP78Ofen9CGeh365zlYws0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c4uQA1/dJMcaa4P2KJ/WP78Ofen9CGeh365zlYws0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c4uQA1/dJMcaa4P2KJ/WP78Ofen9CGeh365zlYws0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc4uQA1%2FdJMcaa4P2KJ%2FWP78Ofen9CGeh365zlYws0%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;2026&quot; height=&quot;499&quot; data-origin-width=&quot;2026&quot; data-origin-height=&quot;499&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1년은 무슨 반년 정도 되는 것 같넹&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;작년에는 ICPC에 관심이 없었던 것 같다. 암튼 열심히 하다 보니 나가고 싶어져서 팀을 만들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀은 &lt;span style=&quot;color: #555555;&quot;&gt;&lt;b&gt;celina324&lt;/b&gt;&lt;/span&gt;, &lt;b&gt;&lt;span style=&quot;color: #555555;&quot;&gt;g_grain&lt;/span&gt;&lt;/b&gt;, &lt;span style=&quot;color: #03a89e;&quot;&gt;&lt;b&gt;jungh150&lt;/b&gt;&lt;/span&gt; 이렇게 구성되어 있고, 지지난번 SUAPC에도 이렇게 나갔던 것 같다.&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;워낙 은채랑 지은이 둘 다 학교에서 잘하는 편이기 때문에 1등을 못할 것 같다는 생각은 없었고, 그래서 가장 중요한 건 학교 별 1등 커트라인 넘기기였다. 그래서 골드 다 풀기를 목표로 계속 팀연습을 했었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;대회&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 한국어 문제 먼저 셋이 하나씩 읽어보기로 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 프린트된 문제지가 오는 데 15분은 걸려서 그동안 작은 노트북 화면에서 화면 분할로 옹기종기 모여서 봤다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;A. 최적의 분할 &lt;span style=&quot;color: #ff0000;&quot;&gt;&lt;b&gt;1WA&lt;/b&gt;&lt;/span&gt; (0:17)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각자 문제를 읽어보다가&amp;nbsp; &lt;span style=&quot;color: #555555;&quot;&gt;&lt;b&gt;celina324&lt;/b&gt;&lt;/span&gt;가 A가 쉬워 보인다고 하면서 이렇게 풀면 되지 않냐고 물어봤다.&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;span style=&quot;color: #03a89e;&quot;&gt;&lt;b&gt;jungh150&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;가 코드를 짜기로 해서 짰는데, 사실 난 다른 문제를 보고 있었어서 이 문제를 제대로 이해하지 못한 상태였고 그냥&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;b&gt; celina324&lt;/b&gt;&lt;/span&gt;가 말한 대로 구현을 했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇게 제출해서 한번 틀린 다음에 문제부터 다시 읽고 풀이를 생각해 보니 반례를 금방 찾을 수 있었다. 내가 코드를 짜기 전에 문제를 읽고 같이 풀이 검증을 좀 하고 짜야 했는데 그러지 못해서 좀 미안했다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;A. 최적의 분할 &lt;span style=&quot;color: #008000;&quot;&gt;&lt;b&gt;CORRECT&lt;/b&gt;&lt;/span&gt; (0:42)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;암튼 그래서 &lt;span style=&quot;color: #03a89e;&quot;&gt;&lt;b&gt;jungh150&lt;/b&gt;&lt;/span&gt;가 A 디버깅을 계속하고, &lt;span style=&quot;color: #555555;&quot;&gt;&lt;b&gt;celina324&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #555555;&quot;&gt;g_grain&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;은 같이 F를 보고 있었던 것 같다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떻게 풀까 고민을 좀 하다가 다시 보니 n이 3000밖에 안 되길래 n 제곱 dp로 해결하면 되겠다 싶어서 바로 그렇게 구현해서 맞았다.&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;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1764950612879&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;

void solve() {
    int n;
    cin &amp;gt;&amp;gt; n;

    vector&amp;lt;int&amp;gt; a(n);
    for (int i = 0; i &amp;lt; n; i++) cin &amp;gt;&amp;gt; a[i];
    vector&amp;lt;int&amp;gt; b(n);
    for (int i = 0; i &amp;lt; n; i++) cin &amp;gt;&amp;gt; b[i];

    vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; adp(n, vector&amp;lt;int&amp;gt;(n));
    vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; bdp(n, vector&amp;lt;int&amp;gt;(n));

    for (int i = 0; i &amp;lt; n; i++) {
        int minidx = i;
        for (int j = i; j &amp;lt; n; j++) {
            adp[i][j] = minidx;
            if (a[j] &amp;lt; a[minidx]) {
                minidx = j;
                adp[i][j] = minidx;
            }
        }
    }

    for (int i = 0; i &amp;lt; n; i++) {
        int minidx = i;
        for (int j = i; j &amp;lt; n; j++) {
            bdp[i][j] = minidx;
            if (b[j] &amp;lt; b[minidx]) {
                minidx = j;
                bdp[i][j] = minidx;
            }
        }
    }

    int ans = 0;
    int s = 0;
    while (s &amp;lt; n) {
        for (int e = n - 1; e &amp;gt;= 0; e--) {
            if (adp[s][e] == bdp[s][e]) {
                s = e + 1;
                ans++;
                break;
            }
        }
    }

    cout &amp;lt;&amp;lt; ans &amp;lt;&amp;lt; '\n';
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int T = 1;
    for (int i = 0; i &amp;lt; T; i++) {
        solve();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;F. Inverse Look-and-Say &lt;span style=&quot;color: #ff0000;&quot;&gt;&lt;b&gt;1WA&lt;/b&gt;&lt;/span&gt; (0:59)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A를 풀고 나서 F를 보고 있던 &lt;span style=&quot;color: #555555;&quot;&gt;&lt;b&gt;celina324&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;b&gt;g_grain&lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span&gt; 쪽으로 갔더니 간단히 문제 설명을 해줬다. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span&gt;둘은 그냥 쭉 읽어보면서 풀면 쉬운데 입력 크기가 너무 커서 어떻게 해야 되는지 모르겠다며 규칙을 찾아야 되나 고민하고 있었다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span&gt;입력을 봤는데 문자열로 읽는다 쳤을 때 길이가 1000밖에 안되어서 왜 고민 중인 거지? 싶었다. 그래서 그냥 읽으면서 확인하면 되는 거 아니냐고 물어보니 둘이 엥 그러네??? 했다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span&gt;그래서 다시 &lt;span style=&quot;color: #03a89e;&quot;&gt;&lt;b&gt;jungh150&lt;/b&gt;&lt;/span&gt;가 컴퓨터 쪽으로 와서 풀었는데 틀렸다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;F.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Inverse Look-and-Say &lt;span style=&quot;color: #ff0000;&quot;&gt;&lt;b&gt;3WA&lt;/b&gt;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&lt;b&gt;CORRECT&lt;/b&gt;&lt;/span&gt; (1:33)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다 같이 디버깅을 하다가 &lt;span style=&quot;color: #555555;&quot;&gt;&lt;b&gt;celina324&lt;/b&gt;&lt;/span&gt;는 I를 보러 가고 &lt;span style=&quot;color: #03a89e;&quot;&gt;&lt;b&gt;jungh150&lt;/b&gt;&lt;/span&gt;와 &lt;b&gt;&lt;span style=&quot;color: #555555;&quot;&gt;g_grain&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span&gt;이 F 디버깅을 했다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span&gt;위에서 말했듯 좀 시간이 지난 뒤에 후기를 적는 거라 어느 순간에 뭘 고쳐서 제출했는지 정확히는 기억이 안 나지만 대략적인 흐름은 이랬다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #03a89e;&quot;&gt;&lt;b&gt;jungh150&lt;/b&gt;&lt;/span&gt;가 아! 이런 경우도 생각해야 되네 하고 제출하고 틀리고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 &lt;span style=&quot;color: #03a89e;&quot;&gt;&lt;b&gt;jungh150&lt;/b&gt;&lt;/span&gt;가 아 이거 때문인가? 하고 제출하고 틀리고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt; &lt;b&gt;g_grain&lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span&gt;이 아!! 0이면 어쩌구 저쩌구 해서 &lt;span style=&quot;color: #03a89e;&quot;&gt;&lt;b&gt;jungh150&lt;/b&gt;&lt;/span&gt;가 아 맞네! 하고 제출하고 틀리고&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #03a89e;&quot;&gt;&lt;b&gt;jungh150&lt;/b&gt;&lt;/span&gt;가 아 0일 때 이것도 처리해야 되네 하고 제출하고 맞았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1764951537504&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;

void solve() {
    string s;
    cin &amp;gt;&amp;gt; s;

    int n = s.size();

    if (n % 2 == 1) {
        cout &amp;lt;&amp;lt; -1 &amp;lt;&amp;lt; '\n';
        return;
    }

    string ans = &quot;&quot;;
    for (int i = 0; i &amp;lt; n; i += 2) {
        char a = s[i];
        char b = s[i + 1];
        if (a == '0') {
            cout &amp;lt;&amp;lt; -1 &amp;lt;&amp;lt; '\n';
            return;
        }
        if (b == '0' &amp;amp;&amp;amp; i == 0) {
            cout &amp;lt;&amp;lt; -1 &amp;lt;&amp;lt; '\n';
            return;
        }
        if (i &amp;gt;= 2 &amp;amp;&amp;amp; b == s[i - 1]) {
            cout &amp;lt;&amp;lt; -1 &amp;lt;&amp;lt; '\n';
            return;
        }
        for (int j = 0; j &amp;lt; a - '0'; j++) ans += b;
    }
    
    cout &amp;lt;&amp;lt; ans &amp;lt;&amp;lt; '\n';
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int T = 1;
    for (int i = 0; i &amp;lt; T; i++) {
        solve();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;I. 이차 방정식 &lt;span style=&quot;color: #008000;&quot;&gt;&lt;b&gt;CORRECT&lt;/b&gt; &lt;/span&gt;(2:47)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;풀고 나서 다 같이 I를 봤다. 진짜 어떻게 푸는 건지 감이 안 왔다.&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 data-ke-size=&quot;size16&quot;&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;span style=&quot;color: #03a89e;&quot;&gt;&lt;b&gt;jungh150&lt;/b&gt;&lt;/span&gt;는 규칙이 보일까 싶어 탐색 범위를 널널하게 잡은 브루트포스 코드를 짜서 돌려보고 있었고, &lt;b&gt;&lt;span style=&quot;color: #555555;&quot;&gt;g_grain&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span&gt;과&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;b&gt;celina324&lt;/b&gt;&lt;/span&gt;는 옆에서 뭔가 엄청 열심히 적고 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #555555;&quot;&gt;g_grain&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span&gt;이 근의 공식에서 (p^2-4kp) 가 제곱수가 되려면 p에 대한 이차 함수를 그려봤을 때 p=2k 대칭이니까 p의 합은 결국 2k * (p의 개수)라는 엄청난 발견을 해냈다!&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span&gt;그 말을 들은 멍청한 &lt;span style=&quot;color: #03a89e;&quot;&gt;&lt;b&gt;jungh150&lt;/b&gt;&lt;/span&gt;가 오 대박!! 그러네!! 천재당 그럼 이제 어케 하지?를 시전하고 있을 때, &lt;span style=&quot;color: #555555;&quot;&gt;&lt;b&gt;celina324&lt;/b&gt;&lt;/span&gt;가 자기가 규칙을 찾은 것 같다면서 내 코드를 돌려볼 수 있냐고 물어봤다. 그래서 &lt;span style=&quot;color: #555555;&quot;&gt;&lt;b&gt;celina324&lt;/b&gt;&lt;/span&gt;가 불러주는 예제들을 넣어보니 전부 다 잘 나오는 거다!!&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;b&gt;celina324&lt;/b&gt;&lt;/span&gt;한테 어떻게 한거냐고 물어보니까 뭐라고 설명해줬는데 사실 잘 기억이 안 난다. 너무 흥분한 상태이기도 하고 시간이 많이 남은 상황은 아니었어서 마음이 급해서 이해가 잘 안 됐다.&lt;/span&gt;&lt;/span&gt;&lt;/span&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;span style=&quot;color: #555555;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span&gt;그래서 그냥 답을 어떻게 구하면 되는 건지 물어봐서 &lt;span style=&quot;color: #03a89e;&quot;&gt;&lt;b&gt;jungh150&lt;/b&gt;&lt;/span&gt;가 그걸 그대로 구현해서 냈고 맞았다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span&gt;솔직히 기대 안 하고 냈는데 한 번에 맞아서 깜짝 놀랐고 도파민이 미쳤었고 손이 떨렸었다. 시간도 13분밖에 안 남은 상태로 맞아서 더 그랬다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span&gt;다 같이 은채 복복복 삼만번 정도 하고 나서 슼보를 봤더니 우리 학교 중에 3솔 한 팀이 없었기 때문에 본선 진출하겠다고 생각하고 남은 시간을 편하게 보냈던 것 같다.&lt;/span&gt;&lt;/span&gt;&lt;/span&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;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1764962185264&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;

void solve() {
    long long k;
    cin &amp;gt;&amp;gt; k;

    long long n = 4 * k * k;
    vector&amp;lt;long long&amp;gt; a;
    for (long long x = 1; x &amp;lt; sqrt(n) + 1; x++) {
        if (n % x == 0) {
            if ((x + n/x) % 2 == 0) {
                a.push_back(x);
                a.push_back(n / x);
            }
        }
    }

    long long sz = a.size();
    cout &amp;lt;&amp;lt; sz &amp;lt;&amp;lt; ' ' &amp;lt;&amp;lt; 2 * k * sz &amp;lt;&amp;lt; '\n';
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int T = 1;
    for (int i = 0; i &amp;lt; T; i++) {
        solve();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;1766&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHgd3q/dJMb99LEb38/SN89FDWmNkjrkdrBjibLVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHgd3q/dJMb99LEb38/SN89FDWmNkjrkdrBjibLVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHgd3q/dJMb99LEb38/SN89FDWmNkjrkdrBjibLVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHgd3q%2FdJMb99LEb38%2FSN89FDWmNkjrkdrBjibLVk%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;3000&quot; height=&quot;1766&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;1766&quot;/&gt;&lt;/span&gt;&lt;/figure&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;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2357&quot; data-origin-height=&quot;2733&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OIied/dJMcadmVlq2/uJO404i6hlsKkUokkak991/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OIied/dJMcadmVlq2/uJO404i6hlsKkUokkak991/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OIied/dJMcadmVlq2/uJO404i6hlsKkUokkak991/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOIied%2FdJMcadmVlq2%2FuJO404i6hlsKkUokkak991%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;683&quot; height=&quot;792&quot; data-origin-width=&quot;2357&quot; data-origin-height=&quot;2733&quot;/&gt;&lt;/span&gt;&lt;/figure&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;우선 문제에 나와있는 방정식인 x^2 + px + kp = 0에 근의 공식을 적용한다. 근이 정수여야 하므로 그 식에서 루트 안에 있는 항이 제곱수여야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;참고로,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;p가 짝수이면 p^2은 4의 배수고, 루트 안의 항이 4의 배수기 때문에 루트 벗겨도 짝수고, 분자가 전부 짝수여서 전체는 정수&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;p가 홀수이면 p^2 홀수고 -4kp는 짝수니까 둘을 더한 건 홀수로, 루트 벗겨도 홀수고, 분자가 홀수+홀수여서 짝수니까 전체는 정수&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;따라서, 루트 안의 항이 제곱수이기만 하면 근은 항상 정수를 만족한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;(이걸 대회 때는 증명하지 못했는데 자연스럽게 성립하는 거여서 다행이었다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;루트 안에 있는 항이 제곱수여야 한다는 것을 p^2 - kp = q^2 (q는 정수) 라고 표현한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 완전제곱으로 묶기 위해서 4k^2을 더해주고 빼준다. 그러면 (p - 2k)^2 이런 식으로 묶이게 되고, 4k^2은 우항으로 넘긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좌항인 (p - 2k)^2 - q^2에 합차 공식을 적용하면 (p - 2k + q)(p - 2k - q) = 4k^2 이런 식으로 정리할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어느 정도 식 정리는 되었는데, 좀 더 편하게 보기 위해서 p - 2k = p' 라고 치환해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;p가 정수니까 p'도 정수여야 하고, q도 정수이다. 두 정수의 곱이 4k^2이라는 것은 둘은 서로 쌍이 되는 4k^2의 약수라는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단, 이 두 약수의 차이는 짝수여야 한다. 두 수의 차이가 2q이기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 4k^2의 약수 쌍(둘 다 4k^2으로 나눠지면서 곱하면 4k^2이 되는 두 수)들을 보면서 차가 짝수인 수들의 개수를 세면 된다.&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;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1765038235346&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;

void solve() {
    long long k;
    cin &amp;gt;&amp;gt; k;

    long long n = 4 * k * k;
    long long cnt = 0;
    for (long long x = 1; x &amp;lt; sqrt(n) + 1; x++) {
        if (n % x == 0) {
            if (abs(n/x - x) % 2 == 0) cnt += 2;
        }
    }

    cout &amp;lt;&amp;lt; cnt &amp;lt;&amp;lt; ' ' &amp;lt;&amp;lt; 2 * k * cnt &amp;lt;&amp;lt; '\n';
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int T = 1;
    for (int i = 0; i &amp;lt; T; i++) {
        solve();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2532&quot; data-origin-height=&quot;1346&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nArns/dJMcag43YQO/izR2xKgbPKWHoKDI2qmdmK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nArns/dJMcag43YQO/izR2xKgbPKWHoKDI2qmdmK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nArns/dJMcag43YQO/izR2xKgbPKWHoKDI2qmdmK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnArns%2FdJMcag43YQO%2FizR2xKgbPKWHoKDI2qmdmK%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;2532&quot; height=&quot;1346&quot; data-origin-width=&quot;2532&quot; data-origin-height=&quot;1346&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대회 종료 12분 전 스코어보드(프리즈 상태)이다. 이때는 106등이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;대회 후&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2539&quot; data-origin-height=&quot;1350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGfK1N/dJMcadtGDMP/37YGGwiPoGGKpRTkKdivJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGfK1N/dJMcadtGDMP/37YGGwiPoGGKpRTkKdivJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGfK1N/dJMcadtGDMP/37YGGwiPoGGKpRTkKdivJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGfK1N%2FdJMcadtGDMP%2F37YGGwiPoGGKpRTkKdivJk%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;2539&quot; height=&quot;1350&quot; data-origin-width=&quot;2539&quot; data-origin-height=&quot;1350&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최종 스코어보드이다. 84등으로 마무리했고, 학교 1등으로 본선에 진출하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 학교별 1등 커트라인은 2솔이었다. I를 못 풀어도 갈 수 있었기에 은채는 살짝 아쉬워했지만 나는 그래도 3솔로 당당히? 갈 수 있어서 좋았다!!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;2559&quot; data-origin-height=&quot;1145&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5PTKp/dJMcahCUn29/4qUvTOSJRjMayX3q5l3zjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5PTKp/dJMcahCUn29/4qUvTOSJRjMayX3q5l3zjk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5PTKp/dJMcahCUn29/4qUvTOSJRjMayX3q5l3zjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5PTKp%2FdJMcahCUn29%2F4qUvTOSJRjMayX3q5l3zjk%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;2559&quot; height=&quot;1145&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;2559&quot; data-origin-height=&quot;1145&quot;/&gt;&lt;/span&gt;&lt;/figure&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;후기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A는 예상보다 티어가 살짝 높았는데 I가 예상보다 좀 낮았다. 나는 수학을 못하는 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ICPC 예선을 참여하면서 포기한 것들이 있는데, 그래도 본선에 나갈 수 있어서 후회는 없고 다행인 것 같다.&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>Contest</category>
      <category>cp</category>
      <category>ICPC</category>
      <category>PS</category>
      <category>대회 후기</category>
      <author>jungh150c</author>
      <guid isPermaLink="true">https://jungh150c.tistory.com/325</guid>
      <comments>https://jungh150c.tistory.com/325#entry325comment</comments>
      <pubDate>Sun, 7 Dec 2025 01:35:29 +0900</pubDate>
    </item>
    <item>
      <title>[C++] 열혈강호 5 (백준 11408번) - 최소 비용 최대 유량 (Min Cost Max Flow)</title>
      <link>https://jungh150c.tistory.com/324</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1158&quot; data-origin-height=&quot;554&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CdiKO/dJMcahpnS70/cTxss7OO1jriLoZmVYIGWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CdiKO/dJMcahpnS70/cTxss7OO1jriLoZmVYIGWK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CdiKO/dJMcahpnS70/cTxss7OO1jriLoZmVYIGWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCdiKO%2FdJMcahpnS70%2FcTxss7OO1jriLoZmVYIGWK%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;1158&quot; height=&quot;554&quot; data-origin-width=&quot;1158&quot; data-origin-height=&quot;554&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/11408&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/11408&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dnCV4y/dJMcahiBz7z/yKKxuQ1FvuGCpnatY3DJLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dnCV4y/dJMcahiBz7z/yKKxuQ1FvuGCpnatY3DJLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dnCV4y/dJMcahiBz7z/yKKxuQ1FvuGCpnatY3DJLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdnCV4y%2FdJMcahiBz7z%2FyKKxuQ1FvuGCpnatY3DJLK%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;573&quot; height=&quot;382&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1498&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZfSTK/dJMcadtHiA8/WSwDCrGKOCDpR5pkz8nFsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZfSTK/dJMcadtHiA8/WSwDCrGKOCDpR5pkz8nFsk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZfSTK/dJMcadtHiA8/WSwDCrGKOCDpR5pkz8nFsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZfSTK%2FdJMcadtHiA8%2FWSwDCrGKOCDpR5pkz8nFsk%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;580&quot; height=&quot;387&quot; data-origin-width=&quot;1498&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적인&amp;nbsp;최대&amp;nbsp;유량&amp;nbsp;문제&amp;nbsp;풀듯이&amp;nbsp;하되,&amp;nbsp;각&amp;nbsp;단계마다&amp;nbsp;현재&amp;nbsp;잔여&amp;nbsp;그래프에서&amp;nbsp;최단&amp;nbsp;거리&amp;nbsp;알고리즘을&amp;nbsp;이용해&amp;nbsp;최소&amp;nbsp;비용&amp;nbsp;증가&amp;nbsp;경로를&amp;nbsp;찾고,&amp;nbsp;그&amp;nbsp;경로로&amp;nbsp;유량을&amp;nbsp;흘려준다.&amp;nbsp;최단&amp;nbsp;거리를&amp;nbsp;구할&amp;nbsp;때는&amp;nbsp;벨만&amp;nbsp;포드&amp;nbsp;알고리즘을&amp;nbsp;약간&amp;nbsp;변형시켜&amp;nbsp;평균&amp;nbsp;실행&amp;nbsp;시간을&amp;nbsp;줄인&amp;nbsp;SPFA를&amp;nbsp;사용하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1764946519288&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Reference: green55 teamnote
// https://github.com/green5555/Teamnote/blob/master/TeamNote/MCMF.cpp

#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;

typedef long long ll;
typedef pair&amp;lt;ll, ll&amp;gt; pll;

//O(VEf), Average = O(Ef)
const int MAX=2010;
struct MinCostMaxFlow{
    struct edg{ int pos, cap, rev; ll cost; };
    vector&amp;lt;edg&amp;gt; adj[MAX];
    void clear(){
        for(int i=0; i&amp;lt;MAX; i++) adj[i].clear();
    }
    void add_edge(int from, int to, int cap, int cost){
        adj[from].push_back({to, cap, (int)adj[to].size(), cost});
        adj[to].push_back({from, 0, (int)adj[from].size()-1, -cost});
    }
    ll dist[MAX];
    int pa[MAX], pe[MAX];
    bool inque[MAX];
    bool spfa(int src, int sink){
        memset(dist, 0x3f, sizeof(dist));
        memset(inque, 0, sizeof(inque));
        queue&amp;lt;int&amp;gt; que;
        dist[src] = 0;
        inque[src] = 1;
        que.push(src);
        bool ok = 0;
        while(!que.empty()){
            int x = que.front();
            que.pop();
            if(x == sink) ok = 1;
            inque[x] = 0;
            for(int i=0; i&amp;lt;adj[x].size(); i++){
                edg e = adj[x][i];
                if(e.cap &amp;gt; 0 &amp;amp;&amp;amp; dist[e.pos] &amp;gt; dist[x] + e.cost){
                    dist[e.pos] = dist[x] + e.cost;
                    pa[e.pos] = x;
                    pe[e.pos] = i;
                    if(!inque[e.pos]){
                        inque[e.pos] = 1;
                        que.push(e.pos);
                    }
                }
            }
        }
        return ok;
    }
    pll match(int src, int sink){
        ll min_cost=0, max_flow=0;
        while(spfa(src, sink)){
            int cap = 1e9;
            for(int pos = sink; pos != src; pos = pa[pos]){
                cap = min(cap, adj[pa[pos]][pe[pos]].cap);
            }
            min_cost += dist[sink] * cap;
            max_flow += cap;
            for(int pos = sink; pos != src; pos = pa[pos]){
                int rev = adj[pa[pos]][pe[pos]].rev;
                adj[pa[pos]][pe[pos]].cap -= cap;
                adj[pos][rev].cap += cap;
            }
        }
        return {min_cost, max_flow};
    }
};

void solve() {
    MinCostMaxFlow mcmf;

    int n, m;
    cin &amp;gt;&amp;gt; n &amp;gt;&amp;gt; m;

    for (int i = 1; i &amp;lt; n + 1; i++) {
        int cnt;
        cin &amp;gt;&amp;gt; cnt;
        mcmf.add_edge(2008, i, 1, 0); // s -&amp;gt; 직원
        while (cnt--) {
            int j, x;
            cin &amp;gt;&amp;gt; j &amp;gt;&amp;gt; x;
            mcmf.add_edge(i, j + 1000, 1, x); // 직원 -&amp;gt; 일
        }
    }

    for (int j = 1; j &amp;lt; m + 1; j++) {
        mcmf.add_edge(j + 1000, 2009, 1, 0); // 일 -&amp;gt; t
    }

    pll ans = mcmf.match(2008, 2009);
    cout &amp;lt;&amp;lt; ans.second &amp;lt;&amp;lt; '\n' &amp;lt;&amp;lt; ans.first &amp;lt;&amp;lt; '\n';
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int T = 1;
    for (int i = 0; i &amp;lt; T; i++) {
        solve();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(AC)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>PS</category>
      <category>C++</category>
      <category>그래프</category>
      <category>최대 유량</category>
      <category>최소 비용 최대 유량</category>
      <author>jungh150c</author>
      <guid isPermaLink="true">https://jungh150c.tistory.com/324</guid>
      <comments>https://jungh150c.tistory.com/324#entry324comment</comments>
      <pubDate>Sat, 6 Dec 2025 00:18:04 +0900</pubDate>
    </item>
    <item>
      <title>[C++] 열혈강호 3 (백준 11377번)</title>
      <link>https://jungh150c.tistory.com/323</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2014&quot; data-origin-height=&quot;776&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IfhZ9/dJMcacawHAk/VyefPusG4fiRb2acAvtzP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IfhZ9/dJMcacawHAk/VyefPusG4fiRb2acAvtzP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IfhZ9/dJMcacawHAk/VyefPusG4fiRb2acAvtzP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIfhZ9%2FdJMcacawHAk%2FVyefPusG4fiRb2acAvtzP0%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;2014&quot; height=&quot;776&quot; data-origin-width=&quot;2014&quot; data-origin-height=&quot;776&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/11377&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/11377&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1572&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bh57Ga/dJMcadNZkx3/9XDGfC3LxDpkieAZOXu0MK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bh57Ga/dJMcadNZkx3/9XDGfC3LxDpkieAZOXu0MK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bh57Ga/dJMcadNZkx3/9XDGfC3LxDpkieAZOXu0MK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbh57Ga%2FdJMcadNZkx3%2F9XDGfC3LxDpkieAZOXu0MK%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;671&quot; height=&quot;427&quot; data-origin-width=&quot;1572&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 중간 노드를 하나 만들어서 거기로 k만큼 흘려주도록 모델링하면&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1563&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Rf6Rd/dJMcadAsiBd/kxpBBcxCMWkSCCYfmiPTj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Rf6Rd/dJMcadAsiBd/kxpBBcxCMWkSCCYfmiPTj1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Rf6Rd/dJMcadAsiBd/kxpBBcxCMWkSCCYfmiPTj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRf6Rd%2FdJMcadAsiBd%2FkxpBBcxCMWkSCCYfmiPTj1%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;678&quot; height=&quot;434&quot; data-origin-width=&quot;1563&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/figure&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;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1764934359730&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Reference: green55 teamnote
// https://github.com/green5555/Teamnote/blob/master/TeamNote/Ed-Karp.cpp

#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;

typedef pair&amp;lt;int, int&amp;gt; pii;

const int MAX = 2010, INF = INT_MAX;
struct maxflow {
    struct edge {
        int next, cap, flow = 0, rev_idx;
        edge() {}
        edge(int n, int c) : next(n), cap(c) {}
        int remain() {
            return cap - flow;
        }
    };
    vector&amp;lt;edge&amp;gt; adj[MAX];
    void makeEdge(int u, int v, int c) {
        adj[u].emplace_back(v, c);
        adj[v].emplace_back(u, 0);
        adj[u].back().rev_idx = adj[v].size() - 1;
        adj[v].back().rev_idx = adj[u].size() - 1;
    }
    int parent[MAX];
    pii path[MAX];
    int solve(int S, int E) {
        int ans = 0;
        queue&amp;lt;int&amp;gt; q;
        while (1) {
            memset(parent, -1, sizeof(parent));
            q.push(S);
            while (!q.empty()) {
                int u = q.front(); q.pop();
                for (int i = 0; i &amp;lt; adj[u].size(); ++i) {
                    auto &amp;amp;e = adj[u][i];
                    if (e.remain() &amp;gt; 0 &amp;amp;&amp;amp; parent[e.next] == -1) {
                        parent[e.next] = u;
                        path[e.next] = { u, i };
                        q.emplace(e.next);
                    }
                }
            }
            if (parent[E] == -1) break;
            int ret = INF;
            for (int i = E; i != S; i = parent[i])
                ret = min(ret, adj[path[i].first][path[i].second].remain());
            for (int i = E; i != S; i = parent[i]) {
                auto &amp;amp;e = adj[path[i].first][path[i].second];
                e.flow += ret;
                adj[e.next][e.rev_idx].flow -= ret;
            }
            ans += ret;
        }
        return ans;
    }
};

void solve() {
    maxflow mf;

    int n, m, k;
    cin &amp;gt;&amp;gt; n &amp;gt;&amp;gt; m &amp;gt;&amp;gt; k;

    mf.makeEdge(2008, 2007, k); // s -&amp;gt; 중간 노드
    for (int i = 1; i &amp;lt; n + 1; i++) {
        int cnt;
        cin &amp;gt;&amp;gt; cnt;
        mf.makeEdge(2008, i, 1); // s -&amp;gt; 직원
        mf.makeEdge(2007, i, 1); // 중간 노드 -&amp;gt; 직원
        while (cnt--) {
            int j;
            cin &amp;gt;&amp;gt; j;
            mf.makeEdge(i, j + 1000, 1); // 직원 -&amp;gt; 일
        }
    }

    for (int j = 1; j &amp;lt; m + 1; j++) {
        mf.makeEdge(j + 1000, 2009, 1); // 일 -&amp;gt; t
    }

    cout &amp;lt;&amp;lt; mf.solve(2008, 2009) &amp;lt;&amp;lt; '\n';
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int T = 1;
    for (int i = 0; i &amp;lt; T; i++) {
        solve();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(AC)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>PS</category>
      <category>C++</category>
      <category>그래프</category>
      <category>이분 매칭</category>
      <category>최대 유량</category>
      <author>jungh150c</author>
      <guid isPermaLink="true">https://jungh150c.tistory.com/323</guid>
      <comments>https://jungh150c.tistory.com/323#entry323comment</comments>
      <pubDate>Fri, 5 Dec 2025 20:53:20 +0900</pubDate>
    </item>
    <item>
      <title>[C++] 북서풍 (백준 5419번) - 스위핑 + 세그먼트 트리</title>
      <link>https://jungh150c.tistory.com/322</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1162&quot; data-origin-height=&quot;444&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byYlwr/dJMcaf54GKB/ZQRrkuiXWXpt1LJACZKGzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byYlwr/dJMcaf54GKB/ZQRrkuiXWXpt1LJACZKGzk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byYlwr/dJMcaf54GKB/ZQRrkuiXWXpt1LJACZKGzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyYlwr%2FdJMcaf54GKB%2FZQRrkuiXWXpt1LJACZKGzk%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;1162&quot; height=&quot;444&quot; data-origin-width=&quot;1162&quot; data-origin-height=&quot;444&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/5419&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/5419&lt;/a&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;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;각 섬마다 자신보다 북서쪽에 있는 섬들이 몇 개인지&lt;/b&gt; -&amp;gt; 그것들의 합을 구하면 정답&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러므로 섬들을 &lt;b&gt;x 기준 오름차순, y 기준 내림차순&lt;/b&gt;으로 정렬해두자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇게 정렬해둔 다음에, &lt;b&gt;앞에서부터 보면서&lt;/b&gt; 각 섬 기준 북서쪽에 있는 섬들이 몇 개인지 셀 때 지금까지 본 섬 중 &lt;b&gt;자기보다 y값이 크거나 같은 섬이 몇 개였는지&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;&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;지금까지 본 섬들 중 자기보다 y값이 크거나 같은 섬이 몇 개인지를 빠르게 구하기 위해서 세그먼트 트리를 사용해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; &lt;b&gt;세그먼트 트리에 저장해야 하는 값: 지금까지 본 섬들의 y값 분포&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;p.s. 좌표 압축&lt;/b&gt;&lt;/u&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;y값들에&amp;nbsp;대해서만&amp;nbsp;좌표&amp;nbsp;압축을&amp;nbsp;해주면&amp;nbsp;된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1763657702588&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;vector&amp;gt;
#include &amp;lt;algorithm&amp;gt;
using namespace std;

int ysz;

struct SegTree {
    vector&amp;lt;long long&amp;gt; tree;

    long long update(int idx, int l, int r, int target, long long val) {
        if (target &amp;lt; l || target &amp;gt; r) return tree[idx];
        if (l == r) return tree[idx] = tree[idx] + val;
        int m = (l + r) / 2;
        return tree[idx] = update(idx * 2, l, m, target, val) + update(idx * 2 + 1, m + 1, r, target, val);
    }
    
    long long query(int idx, int l, int r, int wl, int wr) {
        if (wr &amp;lt; l || wl &amp;gt; r) return 0;
        if (wl &amp;lt;= l &amp;amp;&amp;amp; wr &amp;gt;= r) return tree[idx];
        int m = (l + r) / 2;
        return query(idx * 2, l, m, wl, wr) + query(idx * 2 + 1, m + 1, r, wl, wr);
    }
    
    long long update(int target, long long val) {
        return update(1, 0, ysz, target, val);
    }
    
    long long query(int wl, int wr) {
        return query(1, 0, ysz, wl, wr);
    }
};

// x 기준 오름차순, x 같으면 y 기준 내림차순
bool compare(pair&amp;lt;int,int&amp;gt; &amp;amp;a, const pair&amp;lt;int,int&amp;gt; &amp;amp;b) {
    if (a.first == b.first) return a.second &amp;gt; b.second;
    else return a.first &amp;lt; b.first;
}

void solve() {
    int n;
    cin &amp;gt;&amp;gt; n;
    
    vector&amp;lt;pair&amp;lt;int, int&amp;gt;&amp;gt; p(n);
    vector&amp;lt;int&amp;gt; ycom;
    for (int i = 0; i &amp;lt; n; i++) {
        int x, y;
        cin &amp;gt;&amp;gt; x &amp;gt;&amp;gt; y;
        p[i] = {x, y};
        ycom.push_back(y);
    }

    sort(p.begin(), p.end(), compare);
    sort(ycom.begin(), ycom.end());
    ycom.erase(unique(ycom.begin(), ycom.end()), ycom.end());
    
    ysz = ycom.size() + 1;

    SegTree seg; // 지금까지 본 섬들의 y값 별 개수를 저장하는 세그먼트 트리
    seg.tree.assign(4 * ysz + 1, 0);

    long long ans = 0;
    for (auto [x, y]: p) {
        int yidx = lower_bound(ycom.begin(), ycom.end(), y) - ycom.begin();
        ans += seg.query(yidx, ysz);
        seg.update(yidx, 1);
    }

    cout &amp;lt;&amp;lt; ans &amp;lt;&amp;lt; '\n';
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int T = 1;
    cin &amp;gt;&amp;gt; T;
    for (int i = 0; i &amp;lt; T; i++) {
        solve();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(AC)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>PS</category>
      <category>C++</category>
      <category>값 / 좌표 압축</category>
      <category>세그먼트 트리</category>
      <category>스위핑</category>
      <category>자료구조</category>
      <author>jungh150c</author>
      <guid isPermaLink="true">https://jungh150c.tistory.com/322</guid>
      <comments>https://jungh150c.tistory.com/322#entry322comment</comments>
      <pubDate>Fri, 21 Nov 2025 01:56:38 +0900</pubDate>
    </item>
    <item>
      <title>[논문 리뷰] Meerkat: Audio-Visual Large Language  Model for Grounding in Space and Time</title>
      <link>https://jungh150c.tistory.com/321</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.ecva.net/papers/eccv_2024/papers_ECCV/papers/08071.pdf&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.ecva.net/papers/eccv_2024/papers_ECCV/papers/08071.pdf&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2407.01851&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://arxiv.org/abs/2407.01851&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1763438796520&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;Meerkat: Audio-Visual Large Language Model for Grounding in Space and Time&quot; data-og-description=&quot;Leveraging Large Language Models' remarkable proficiency in text-based tasks, recent works on Multi-modal LLMs (MLLMs) extend them to other modalities like vision and audio. However, the progress in these directions has been mostly focused on tasks that on&quot; data-og-host=&quot;arxiv.org&quot; data-og-source-url=&quot;https://arxiv.org/abs/2407.01851&quot; data-og-url=&quot;https://arxiv.org/abs/2407.01851v2&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/7MeZg/hyZOcE9w32/lFd3v0YipyHudckdhWt5R1/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/b89ExC/hyZNXJBCmx/VmQLc12jrQ9hwCHNLCEC10/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2407.01851&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://arxiv.org/abs/2407.01851&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/7MeZg/hyZOcE9w32/lFd3v0YipyHudckdhWt5R1/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/b89ExC/hyZNXJBCmx/VmQLc12jrQ9hwCHNLCEC10/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000');&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;Meerkat: Audio-Visual Large Language Model for Grounding in Space and Time&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Leveraging Large Language Models' remarkable proficiency in text-based tasks, recent works on Multi-modal LLMs (MLLMs) extend them to other modalities like vision and audio. However, the progress in these directions has been mostly focused on tasks that on&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;arxiv.org&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. Introduction&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;LLM의 발전과 멀티모달 확장&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 몇 년간 &lt;b&gt;대규모 언어모델(LLM)&lt;/b&gt;의 비약적인 발전 -&amp;gt; 인간 수준의 이해력과 추론 능력 달성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;instruction fine-tuning (지시 기반 미세조정) 패러다임 도입 -&amp;gt; 자연어 명령어를 이해하고 적합한 작업을 수행할 수 있게 됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 LLM를 &lt;b&gt;다른 모달리티와 결합&lt;/b&gt;하는 흐름으로 확장됨 but 오디오는 상대적으로 덜 연구된 영역&lt;/p&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;기존 연구의 한계: Coarse-grained 중심&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존의 MLLM(멀티모달 LLM)의 한계:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. &lt;b&gt;주로 coarse-grained (거시적인) task에 초점&lt;/b&gt;: 캡셔닝(audio captioning), 질의응답(audio QA) 등의 비교적 단순한 작업&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. &lt;b&gt;fine-grained (세밀한) 오디오-비주얼 이해 부족&lt;/b&gt;: 일부 MLLM을 grounding에 사용하기 시작했지만 여전히 시각 정보에만 집중하거나 세밀한 이해 불가능&lt;/p&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;문제의식과 연구 목표&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연구 목표: &lt;b&gt;LLM을 통해 fine-grained (정밀한) 오디오-비주얼 이해를 달성하고자 함&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;but 어려운 이유:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. &lt;b&gt;입출력 포맷의 다양성&lt;/b&gt;: 서로 다른 과제를 하나의 프레임워크에서 처리해야 함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. &lt;b&gt;대규모 데이터셋의 부재&lt;/b&gt;: grounding&amp;nbsp;학습에&amp;nbsp;적합한&amp;nbsp;audio-visual&amp;nbsp;데이터셋&lt;/p&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;Meerkat 제안: 첫 Unified Audio-Visual LLM&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;기존 모델들&lt;/b&gt;(ex. BuboGPT, TimeChat)&lt;b&gt;의 한계&lt;/b&gt;: coarse-grained&amp;nbsp;task에&amp;nbsp;초점&amp;nbsp;&amp;amp;&amp;nbsp;cross-modality&amp;nbsp;fusion(교차&amp;nbsp;모달&amp;nbsp;결합)이&amp;nbsp;없어&amp;nbsp;fine-grained&amp;nbsp;이해&amp;nbsp;불가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; &lt;b&gt;이 문제들을 해결하기 위해 Meerkat 제안&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Meerkat의 두 가지 핵심 모듈&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. &lt;b&gt;Modality Alignment Module&lt;/b&gt; (모달리티 정렬 모듈): 최적 운송 기반으로 패치 레벨의 약한 감독 학습&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. &lt;b&gt;Cross-modal Attention Consistency Module&lt;/b&gt; (교차 어텐션 일관성 모듈): cross-attention 히트맵을 강제하여 일관성 유지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;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;size18&quot;&gt;&lt;b&gt;MeerkatBench와&amp;nbsp;AVFIT&amp;nbsp;Dataset&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Meerkat 모델을 학습시키고 검증하기 위해 MeerkatBench와 AVFIT Dataset을 함께 제시&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;MeerkatBench:&amp;nbsp;5가지의&amp;nbsp;오디오-비주얼&amp;nbsp;과제를&amp;nbsp;통합한&amp;nbsp;벤치마크&lt;/b&gt; &lt;br /&gt;1)&amp;nbsp;Audio-referred&amp;nbsp;Image&amp;nbsp;Grounding &lt;br /&gt;2)&amp;nbsp;Image-guided&amp;nbsp;Audio&amp;nbsp;Temporal&amp;nbsp;Localization &lt;br /&gt;3)&amp;nbsp;Audio-Visual&amp;nbsp;Fact&amp;nbsp;Checking &lt;br /&gt;4)&amp;nbsp;Audio-Visual&amp;nbsp;Question&amp;nbsp;Answering &lt;br /&gt;5)&amp;nbsp;Audio-Visual&amp;nbsp;Captioning&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AVFIT&amp;nbsp;Dataset&lt;/b&gt; &lt;br /&gt;약&amp;nbsp;3백만(3M)개의&amp;nbsp;instruction-tuning&amp;nbsp;샘플로&amp;nbsp;구성된&amp;nbsp;대규모&amp;nbsp;데이터셋 &lt;br /&gt;fine-grained&amp;nbsp;오디오-비주얼&amp;nbsp;이해를&amp;nbsp;학습하도록&amp;nbsp;설계됨&lt;/p&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;주요 기여&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. &lt;b&gt;세밀한 공간적/시간적 gounding이 가능한 최초의 오디오-비주얼 LLM인 Meerkat 제시&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. &lt;b&gt;5가지 오디오-비주얼 학습 과제를 통합한 MeerkatBench와 대규모 AVFIT dataset 제시&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. &lt;b&gt;모든&amp;nbsp;벤치마크&amp;nbsp;과제에서&amp;nbsp;State-of-the-Art&amp;nbsp;성능&amp;nbsp;달성&lt;/b&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. Related&amp;nbsp;Works&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Multi-modal Large Language Models&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LLM의 지시 수행 (instruction-following) 능력 -&amp;gt; LLM을 다른 모달리티로 확장하려는 흐름&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;LLM을 멀티모달로 확장하기 위한 두 가지 주요 접근 방식&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 1. Latent Alignment 방식&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; LLM은 고정하고 학습된 비주얼 인코더를 통해 latent alignment (잠재 공간 정렬) 학습&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ex. MiniGPT-4,&amp;nbsp;X-LLM,&amp;nbsp;Video-ChatGPT&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 2. Cross-attention 삽입 방식&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; LLM 내부에 cross-attention 층을 추가하여 멀티모달 정보를 처리할 수 있도록&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ex. Otter,&amp;nbsp;LLaMA-Adapter&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;기존 연구의 한계&lt;/b&gt;: 대부분 시각 정보에 집중, coarse-grained tasks 위주&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 연구의 목표&lt;/b&gt;: LLM에 강한 오디오-비주얼 이해 능력 부여&lt;/p&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;Fine-grained Multi-modal Understanding&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;범용 MLLM의 발전 -&amp;gt; 비전-언어(vision-language) 혹은 비디오 이해(video understanding) 과제를 통합적으로 다룰 수 있게 됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+ MLLM에 region-based grounding tasks(영역 기반 그라운딩 과제)를 통합시키려는 시도도 나타남&lt;/p&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;: 오디오-비주얼 과제 통합 프레임워크 제시&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. Methodology&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1542&quot; data-origin-height=&quot;871&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckVFwF/dJMcahJyLgF/zOCixfqzgOGpZsPTm2xst1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckVFwF/dJMcahJyLgF/zOCixfqzgOGpZsPTm2xst1/img.png&quot; data-alt=&quot;Meerkat의 전체적인 구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckVFwF/dJMcahJyLgF/zOCixfqzgOGpZsPTm2xst1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FckVFwF%2FdJMcahJyLgF%2FzOCixfqzgOGpZsPTm2xst1%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;1542&quot; height=&quot;871&quot; data-origin-width=&quot;1542&quot; data-origin-height=&quot;871&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Meerkat의 전체적인 구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.1. Multi-modal&amp;nbsp;Feature&amp;nbsp;Extraction&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Image Encoder (이미지 특징 추출)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 배치에 k 장의 이미지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-11-17 034658.png&quot; data-origin-width=&quot;528&quot; data-origin-height=&quot;56&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c1ixAb/dJMcahiuhVt/XlH2hSk2bKYtK87PhIKlKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c1ixAb/dJMcahiuhVt/XlH2hSk2bKYtK87PhIKlKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c1ixAb/dJMcahiuhVt/XlH2hSk2bKYtK87PhIKlKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc1ixAb%2FdJMcahiuhVt%2FXlH2hSk2bKYtK87PhIKlKK%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;302&quot; height=&quot;32&quot; data-filename=&quot;스크린샷 2025-11-17 034658.png&quot; data-origin-width=&quot;528&quot; data-origin-height=&quot;56&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- H: 이미지 높이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- W: 이미지 너비&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- C: 채널 수 (RBG이면 3)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용 모델: CLIP&amp;nbsp;ViT-B/16&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 한 장은 토큰 (패치) 단위로 쪼개진 다음에 패치 임베딩으로 표현됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-11-17 034910.png&quot; data-origin-width=&quot;242&quot; data-origin-height=&quot;48&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ewTp2T/dJMcagDSTeA/c3jwmuHS9QUA4a1Vje55cK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ewTp2T/dJMcagDSTeA/c3jwmuHS9QUA4a1Vje55cK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ewTp2T/dJMcagDSTeA/c3jwmuHS9QUA4a1Vje55cK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FewTp2T%2FdJMcagDSTeA%2Fc3jwmuHS9QUA4a1Vje55cK%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;141&quot; height=&quot;28&quot; data-filename=&quot;스크린샷 2025-11-17 034910.png&quot; data-origin-width=&quot;242&quot; data-origin-height=&quot;48&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- z_I: 이미지 임베딩&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- S_I: 이미지 토큰 (패치) 개수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- D_I: 각 토큰의 임베딩 차원&lt;/p&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;Audio Encoder (오디오 특징 추출)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 배치에 k 개의 오디오&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-11-17 035156.png&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;71&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qQ4Bm/dJMcaihoJ7i/JnWgMlsObALdPE0Ko7W4u0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qQ4Bm/dJMcaihoJ7i/JnWgMlsObALdPE0Ko7W4u0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qQ4Bm/dJMcaihoJ7i/JnWgMlsObALdPE0Ko7W4u0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqQ4Bm%2FdJMcaihoJ7i%2FJnWgMlsObALdPE0Ko7W4u0%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;274&quot; height=&quot;32&quot; data-filename=&quot;스크린샷 2025-11-17 035156.png&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;71&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- F: 스펙트럼 성분 개수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- T: 시간 프레임 개수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용 모델: CLAP&amp;nbsp;Audio&amp;nbsp;Transformer&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오디오 한 개는 토큰 (시간 구간) 단위로 쪼개진 다음에 패치 임베딩으로 표현됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-11-17 035437.png&quot; data-origin-width=&quot;318&quot; data-origin-height=&quot;55&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/s8sfC/dJMcaawTOto/vKDLrCa380eOkbJ9Jdnfx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/s8sfC/dJMcaawTOto/vKDLrCa380eOkbJ9Jdnfx1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/s8sfC/dJMcaawTOto/vKDLrCa380eOkbJ9Jdnfx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fs8sfC%2FdJMcaawTOto%2FvKDLrCa380eOkbJ9Jdnfx1%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;156&quot; height=&quot;27&quot; data-filename=&quot;스크린샷 2025-11-17 035437.png&quot; data-origin-width=&quot;318&quot; data-origin-height=&quot;55&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- z_A: 오디오 임베딩&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- S_A: 오디오 토큰 (시간 구간) 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- D_A: 각 토큰의 임베딩 차원&lt;/p&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;LLM&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용 모델: Llama&amp;nbsp;2-Chat&amp;nbsp;(7B)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;텍스트 명령은 LLM의 토크나이저를 통해 토큰 시퀀스로 변환된 다음에 임베딩으로 변환됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-11-17 040811.png&quot; data-origin-width=&quot;334&quot; data-origin-height=&quot;57&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VWLUj/dJMcahpfZ6c/21ags7KKu487njJ06VlJy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VWLUj/dJMcahpfZ6c/21ags7KKu487njJ06VlJy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VWLUj/dJMcahpfZ6c/21ags7KKu487njJ06VlJy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVWLUj%2FdJMcahpfZ6c%2F21ags7KKu487njJ06VlJy1%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;159&quot; height=&quot;27&quot; data-filename=&quot;스크린샷 2025-11-17 040811.png&quot; data-origin-width=&quot;334&quot; data-origin-height=&quot;57&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- S_T: 텍스트 토큰 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- D_T: 각 토큰의 임베딩 차원&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;gt; 이를 맞춰추기 위해 추가적인 선형 변환 층 (linear&amp;nbsp;projection&amp;nbsp;layer)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지, 오디오 임베딩이 LLM에 맞춰짐 -&amp;gt; LLM이 Meerkat의 통합 인터페이스 역할을 함&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.2. Audio-Visual&amp;nbsp;Feature&amp;nbsp;Alignment&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오디오와 비주얼 간의 의미적 정렬을 학습하기 위해 두 수준의 정렬을 사용&lt;/p&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;1) Audio-Visual Optimal Transport Alignment Module (AVOpT)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; &lt;b&gt;패치 수준의 약한 감독 정렬 (weak supervision, global-level)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설계 동기: fine-grained supervision (세밀한 감독) 학습을 바로 학습시키는 대신, 먼저 weak supervision (약한 감독) 학습을 먼저 시키는 것이 효과적이라는 것이 입증됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배경 연구 1: siamese network에서 EMD(Earth Mover Distance)와 OT(Optimal Transport; 최적 운송) 기반 알고리즘이 사용됨 -&amp;gt; 쿼리 이미지와 서포트 이미지 강 패치 수준의 정렬 수행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배경 연구 2: 비전-언어 모델에서도 OT 기반 방법이 확장되어 사용됨 -&amp;gt; 이미지의 패치와 문장의 단어 간 정렬 수행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배경 연구 3: 한 모달리티를 선형 투영(linear projection)을 통해 다른 모달리티 공간으로 옮겨서 정렬 수행 (OT 대신 선형 투영 사용)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제 인식: CLIP(이미지 인코더)와 CLAP(오디오 인코더)는 각각 따로 학습됨 -&amp;gt; 두 임베딩이 서로 다른 의미 공간(semantic space)에 있음&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; &lt;b&gt;패치 레벨의 정렬&lt;/b&gt;이 &lt;b&gt;이미지와 오디오 사이의 의미적 일관성(semantic consistency)&lt;/b&gt;을 향상시킴 (대조 학습보다 더 나음)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;패치 임베딩 z_I, z_A를 확률 분포로 표현&lt;/b&gt; (각&amp;nbsp;모달리티의&amp;nbsp;임베딩&amp;nbsp;집합을&amp;nbsp;질량이&amp;nbsp;분포된&amp;nbsp;확률&amp;nbsp;공간으로&amp;nbsp;보는&amp;nbsp;것)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1230&quot; data-origin-height=&quot;212&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpd6gt/dJMcaajmK90/xJvn99e1OsFM0jynPFMqoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpd6gt/dJMcaajmK90/xJvn99e1OsFM0jynPFMqoK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpd6gt/dJMcaajmK90/xJvn99e1OsFM0jynPFMqoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbpd6gt%2FdJMcaajmK90%2FxJvn99e1OsFM0jynPFMqoK%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;453&quot; height=&quot;78&quot; data-origin-width=&quot;1230&quot; data-origin-height=&quot;212&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&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;gt; &lt;b&gt;확률 분포 간 Wasserstein Distance (WD = EMD)&lt;/b&gt; 구하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1480&quot; data-origin-height=&quot;122&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nFNBG/dJMcacVMM6s/DNuRzYIdTLRgMNLv76ajN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nFNBG/dJMcacVMM6s/DNuRzYIdTLRgMNLv76ajN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nFNBG/dJMcacVMM6s/DNuRzYIdTLRgMNLv76ajN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnFNBG%2FdJMcacVMM6s%2FDNuRzYIdTLRgMNLv76ajN0%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;654&quot; height=&quot;54&quot; data-origin-width=&quot;1480&quot; data-origin-height=&quot;122&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;요약: AVOpT는 이미지와 오디오의 패치 임베딩을 확률 분포로 보고, Earth Mover&amp;rsquo;s Distance 기반 Optimal Transport 를 이용해 &lt;/b&gt;&lt;b&gt;두&amp;nbsp;분포&amp;nbsp;간&amp;nbsp;최소&amp;nbsp;운송&amp;nbsp;비용을&amp;nbsp;계산함으로써&amp;nbsp;패치&amp;nbsp;수준에서&amp;nbsp;의미적으로&amp;nbsp;일관된&amp;nbsp;약한&amp;nbsp;정렬(weak&amp;nbsp;alignment)을&amp;nbsp;수행하는&amp;nbsp;모듈&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;size18&quot;&gt;&lt;b&gt;2) Audio-Visual Attention Consistency Enforcement Module (AVACE)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; &lt;b&gt;객체 단위의 강한 감독 정렬 (strong supervision, local-level)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설계 동기: AVOpT는 패치 수준의 약한 정렬을 제공하지만, 아직 오디오와 비주얼 간 구체적인 객체 수준(region-level) 인식은 부족함 (상대&amp;nbsp;모달리티의&amp;nbsp;세부&amp;nbsp;정보를&amp;nbsp;충분히&amp;nbsp;반영하지&amp;nbsp;X)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상호정보를&amp;nbsp;주입하기&amp;nbsp;위해&amp;nbsp;&lt;b&gt;Cross-Attention&amp;nbsp;구조&lt;/b&gt;&amp;nbsp;사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제: 주의 분산 (inconsistency) -&amp;gt; 단순 cross-attention만 사용하면 오디오의 attention이 이미지 전체로 퍼짐&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이유: CLAP은 문장-오디오 쌍으로 학습되었기 때문&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; &lt;b&gt;cross-modality attention map 사용 (ground-truth&amp;nbsp;bounding&amp;nbsp;box를&amp;nbsp;이용해&amp;nbsp;마스크&amp;nbsp;M&amp;nbsp;정의)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1624&quot; data-origin-height=&quot;172&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JHqLG/dJMcabig2sw/TtonkDfqTwToBu8IRHxyVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JHqLG/dJMcabig2sw/TtonkDfqTwToBu8IRHxyVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JHqLG/dJMcabig2sw/TtonkDfqTwToBu8IRHxyVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJHqLG%2FdJMcabig2sw%2FTtonkDfqTwToBu8IRHxyVk%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;690&quot; height=&quot;73&quot; data-origin-width=&quot;1624&quot; data-origin-height=&quot;172&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;목표:&amp;nbsp;객체&amp;nbsp;내부(마스크=1)&amp;nbsp;&amp;rarr;&amp;nbsp;attention을&amp;nbsp;최대화&amp;nbsp;/&amp;nbsp;객체&amp;nbsp;외부(마스크=0)&amp;nbsp;&amp;rarr;&amp;nbsp;attention을&amp;nbsp;최소화&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.3. Overall&amp;nbsp;training&amp;nbsp;objective&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;821&quot; data-origin-height=&quot;52&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJYLwB/dJMcacO07AL/RmVj7ORH9WwfHQkvkr8gh1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJYLwB/dJMcacO07AL/RmVj7ORH9WwfHQkvkr8gh1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJYLwB/dJMcacO07AL/RmVj7ORH9WwfHQkvkr8gh1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJYLwB%2FdJMcacO07AL%2FRmVj7ORH9WwfHQkvkr8gh1%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;442&quot; height=&quot;28&quot; data-origin-width=&quot;821&quot; data-origin-height=&quot;52&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1251&quot; data-origin-height=&quot;635&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cU0HU0/dJMcafkFN7N/MtvaNW6i3B2FZ8zHp5kQIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cU0HU0/dJMcafkFN7N/MtvaNW6i3B2FZ8zHp5kQIK/img.png&quot; data-alt=&quot;전체적인 학습 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cU0HU0/dJMcafkFN7N/MtvaNW6i3B2FZ8zHp5kQIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcU0HU0%2FdJMcafkFN7N%2FMtvaNW6i3B2FZ8zHp5kQIK%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;583&quot; height=&quot;296&quot; data-origin-width=&quot;1251&quot; data-origin-height=&quot;635&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;전체적인 학습 과정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. MeerkatBench:&amp;nbsp;A&amp;nbsp;Unified&amp;nbsp;Benchmark&amp;nbsp;Suite&amp;nbsp;for&amp;nbsp;Fine-grained&amp;nbsp;Audio-Visual&amp;nbsp;Understanding&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4.1. Task&amp;nbsp;Overview&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Fine-grained tasks&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) Audio-Referred Image Grounding (ARIG): 주어진 오디오에 대응하는 영상 내 객체의 위치를 찾는 과제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) Image-Guided Audio Temporal Localization (IGATL): 주어진&amp;nbsp;이미지에&amp;nbsp;대응하는&amp;nbsp;오디오의&amp;nbsp;시간&amp;nbsp;구간을&amp;nbsp;찾는&amp;nbsp;과제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3) Audio-Visual Fact Checking (AVFC): 주어진&amp;nbsp;오디오와&amp;nbsp;영상의&amp;nbsp;내용이&amp;nbsp;서로&amp;nbsp;일치하는지&amp;nbsp;판단하는&amp;nbsp;과제&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Coarse-grained tasks&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4) Audio-Visual Question Answering (AVQA): 주어진 오디오+영상 정보를 종합해 자연어 질문에 답하는 과제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5) Audio-Visual Captioning (AVCap): 주어진&amp;nbsp;오디오+영상을&amp;nbsp;종합해&amp;nbsp;문장&amp;nbsp;설명(caption)을&amp;nbsp;생성하는&amp;nbsp;과제&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4.2. AVFIT-3M:&amp;nbsp;Audio&amp;nbsp;Visual&amp;nbsp;Finegrained&amp;nbsp;Instruction&amp;nbsp;Tuning&amp;nbsp;Dataset&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;AVFIT-3M: MeerkatBench의 학습 기반이 되는 대규모 학습 데이터셋&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 총 샘플 수: 약 3백만 (3M) 멀티모달 instruction&amp;ndash;response 쌍&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 형태: 대화식 instruction&amp;ndash;response 형식&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;nbsp;구성&amp;nbsp;방법:&amp;nbsp;2&amp;nbsp;step&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Step 1. Adaptation&amp;nbsp;of&amp;nbsp;Public&amp;nbsp;Datasets&amp;nbsp;(공개&amp;nbsp;데이터셋&amp;nbsp;재구성)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 1) Direct Collection (직접 수집) &amp;lt;- VGG-SS,&amp;nbsp;AVSBench,&amp;nbsp;Flickr-SoundNet,&amp;nbsp;LLP,&amp;nbsp;AVQA,&amp;nbsp;MUSIC-AVQA,&amp;nbsp;VALOR&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 2) Semi-automated Pairing (반자동 구성) &amp;lt;- Openimages, PASCAL, AudioSet, VGG-Sound (사전에 만들어둔 lookup table을 보고 같은 클래스로 매칭시키는 것)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Step 2. GPT-Assisted&amp;nbsp;Instruction&amp;nbsp;Generation&amp;nbsp;(GPT&amp;nbsp;기반&amp;nbsp;지시문&amp;nbsp;생성)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 기존의 instruction tuning 데이터셋들은 주로 coarse-grained task에 초점 -&amp;gt; fine-grained (공간/시간 단위) 오디오-비주얼 이해에는 적합하지 않음. -&amp;gt; 그래서 세 가지 방법으로 이 문제 개선&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 1) 오디오와 연결될 객체의 공간 좌표를 포함 -&amp;gt; region-level 이해 강화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 2) 오디오 이벤트의 시간 구간을 입출력에 포함 -&amp;gt; temporal reasoning 학습 유도&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 3) GPT-3.5로 각 태스크 별 예시를 다양하게 생성 + GPT-4로 재프롬프트하여 품질 향상&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; =&amp;gt; 이 세 과정으로 여러 개의 지시 포맷을 생성 (not specific instruction): 지시 포맷은 special token을 포함함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 학습 시점에 이 스페셜 토큰들이 실제 데이터로 대체되는 것.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. Experiments&amp;nbsp;and&amp;nbsp;Results&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5.1. Baselines&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Meerkat의 독창성: Meerkat은 오디오-비주얼 공간적/시간적 그라운딩을 모두 통합한 최초의 MLLM임&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 따라서 task 별로 가장 유사한 baseline을 선정하여 공정하게 비교함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;task1) ARIG: BuboGPT&amp;rsquo;s&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;task2) IGATL: TimeChat&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;task3) AVFC: X-InstructBLIP&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;task4) AVQA: Macaw-LLM&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;task5)&amp;nbsp;AVCap:&amp;nbsp;PandaGPT,&amp;nbsp;VideoLlama&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5.2. Main&amp;nbsp;Results&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1)&amp;nbsp;Audio-Referred&amp;nbsp;Image&amp;nbsp;Grounding&amp;nbsp;(ARIG)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주어진&amp;nbsp;오디오에&amp;nbsp;대응하는&amp;nbsp;영상&amp;nbsp;내&amp;nbsp;객체의&amp;nbsp;위치를&amp;nbsp;찾는&amp;nbsp;과제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1339&quot; data-origin-height=&quot;559&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcUGqT/dJMcagYbQqv/YAfhxvxdu84ZQGsJxVO1e1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcUGqT/dJMcagYbQqv/YAfhxvxdu84ZQGsJxVO1e1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcUGqT/dJMcagYbQqv/YAfhxvxdu84ZQGsJxVO1e1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcUGqT%2FdJMcagYbQqv%2FYAfhxvxdu84ZQGsJxVO1e1%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;767&quot; height=&quot;320&quot; data-origin-width=&quot;1339&quot; data-origin-height=&quot;559&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) Image-Guided Audio Temporal Localization (IGATL)&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;성능이 좋은 이유: AVOpT,&amp;nbsp;AVACE&amp;nbsp;두&amp;nbsp;가지&amp;nbsp;모듈을&amp;nbsp;사용하기&amp;nbsp;때문&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;650&quot; data-origin-height=&quot;458&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/deheRw/dJMcaacBjtk/VrkmyhHj9sTkKZllsZTDvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/deheRw/dJMcaacBjtk/VrkmyhHj9sTkKZllsZTDvk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/deheRw/dJMcaacBjtk/VrkmyhHj9sTkKZllsZTDvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdeheRw%2FdJMcaacBjtk%2FVrkmyhHj9sTkKZllsZTDvk%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;358&quot; height=&quot;252&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;650&quot; data-origin-height=&quot;458&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3) Audio-Visual Fact Checking (AVFC)&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;학습에 GT 박스나 시간 구간이 직접적으로 사용되지 않음에도 fine-grained task인 이유: global한 장면이 아니라 객체, 시간 구간 등 세부적 정보에 집중해야 하기 때문&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;model의 response: 이진 답변 (True/False)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;type1) 이미지의 박스 안의 개체가 오디오의 소리를 내는지 판단 (공간 중심)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;type2) 이미지 속 객체가 해당 시간 구간의 오디오와 관련이 있는지 판단 (시간 중심)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;type3) 이미지의 박스 안의 객체가 특정 시간 구간의 오디오의 소리와 일치하는지 판단 (공간+시간 통합)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;type4) 오디오가 이미지 속 장면과 관련이 있는지 판단 -&amp;gt; 의미적 매칭 (global, 전반적)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;681&quot; data-origin-height=&quot;476&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lkB9J/dJMcagjAkiB/CwHaDL7hGIhKFs2ccNsvBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lkB9J/dJMcagjAkiB/CwHaDL7hGIhKFs2ccNsvBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lkB9J/dJMcagjAkiB/CwHaDL7hGIhKFs2ccNsvBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlkB9J%2FdJMcagjAkiB%2FCwHaDL7hGIhKFs2ccNsvBK%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;379&quot; height=&quot;265&quot; data-origin-width=&quot;681&quot; data-origin-height=&quot;476&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4) Audio-Visual Question Answering (AVQA)&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;5) Audio-Visual Captioning (AVCap)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주어진 오디오+영상을 종합해 문장 설명(caption)을 생성하는 과제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1337&quot; data-origin-height=&quot;653&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBdt16/dJMcafydbsN/x73rJhhpkCoUVpqIGkNQz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBdt16/dJMcafydbsN/x73rJhhpkCoUVpqIGkNQz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBdt16/dJMcafydbsN/x73rJhhpkCoUVpqIGkNQz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBdt16%2FdJMcafydbsN%2Fx73rJhhpkCoUVpqIGkNQz0%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;760&quot; height=&quot;371&quot; data-origin-width=&quot;1337&quot; data-origin-height=&quot;653&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Meerkat이 coarse-grained 과제에도 잘 확장되는 이유: 정밀한 오디오-비주얼 의미 이해를 학습했기 때문&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;=&amp;gt; Meerkat은 fine-grained task와 coarse-grained task 모두를 처리할 수 있는 범용 멀티모달 모델 (MLLM)&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5.3. Ablation&amp;nbsp;Study&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Study1) 단일&amp;nbsp;과제&amp;nbsp;학습(single-task)&amp;nbsp;vs.&amp;nbsp;통합&amp;nbsp;다중&amp;nbsp;과제&amp;nbsp;학습(multi-task)&amp;nbsp;비교&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;multi-task 학습이 single-task 학습보다 전반적으로 더 좋은 성능&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;fine-grained task로 학습한 모델은 coarse-grained task에서도 매우 좋은 성능을 보임&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반대로, coarse-grained task 학습을 추가한다고 fine-grained task 성능이 크게 향상되지는 않음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; &lt;b&gt;즉, fine-grained task 학습이 훨씬 중요한 역할을 함&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;824&quot; data-origin-height=&quot;545&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buFKKa/dJMcaajm0Im/1Eys9BK309Yiyv8wYHMUKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buFKKa/dJMcaajm0Im/1Eys9BK309Yiyv8wYHMUKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buFKKa/dJMcaajm0Im/1Eys9BK309Yiyv8wYHMUKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuFKKa%2FdJMcaajm0Im%2F1Eys9BK309Yiyv8wYHMUKK%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;462&quot; height=&quot;306&quot; data-origin-width=&quot;824&quot; data-origin-height=&quot;545&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Study2) 전체&amp;nbsp;LLM&amp;nbsp;파라미터&amp;nbsp;미세조정(full&amp;nbsp;fine-tuning)&amp;nbsp;vs.&amp;nbsp;LoRA&amp;nbsp;기반&amp;nbsp;경량&amp;nbsp;미세조정(LoRA&amp;nbsp;fine-tuning)&amp;nbsp;비교&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cf. LoRA(Low-Rank&amp;nbsp;Adaptation):&amp;nbsp;LLM&amp;nbsp;전체&amp;nbsp;파라미터를&amp;nbsp;직접&amp;nbsp;업데이트하지&amp;nbsp;않고,&amp;nbsp;작은&amp;nbsp;low-rank&amp;nbsp;행렬을&amp;nbsp;추가&amp;nbsp;학습함으로써&amp;nbsp;메모리/시간&amp;nbsp;효율적으로&amp;nbsp;fine-tuning하는&amp;nbsp;방법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LoRA rank 값 r = {4, 16, 32}으로 실험&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt;&amp;nbsp;r=4,16는&amp;nbsp;성능&amp;nbsp;낮고&amp;nbsp;&lt;b&gt;r=32는&amp;nbsp;full&amp;nbsp;fine-tuning보다도&amp;nbsp;약간&amp;nbsp;더&amp;nbsp;성능이&amp;nbsp;좋음&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;LoRA가 fine-tuning 시 기존 LLM의 일반화 성질을 보존하면서 필요한 영역만 정교하게 조정한 것&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;495&quot; data-origin-height=&quot;542&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Yn6Tl/dJMcacBuivC/PFmVRFYdEOrSOjlKjO5AqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Yn6Tl/dJMcacBuivC/PFmVRFYdEOrSOjlKjO5AqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Yn6Tl/dJMcacBuivC/PFmVRFYdEOrSOjlKjO5AqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYn6Tl%2FdJMcacBuivC%2FPFmVRFYdEOrSOjlKjO5AqK%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;279&quot; height=&quot;305&quot; data-origin-width=&quot;495&quot; data-origin-height=&quot;542&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5.4. Qualitative&amp;nbsp;Analysis&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정성적 비교로 Meerkat의 강점을 시각적으로 보여줌&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1262&quot; data-origin-height=&quot;862&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Jl57f/dJMcabihhJD/twH71aNiKwK40LVMS98Ef0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Jl57f/dJMcabihhJD/twH71aNiKwK40LVMS98Ef0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Jl57f/dJMcabihhJD/twH71aNiKwK40LVMS98Ef0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJl57f%2FdJMcabihhJD%2FtwH71aNiKwK40LVMS98Ef0%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;1262&quot; height=&quot;862&quot; data-origin-width=&quot;1262&quot; data-origin-height=&quot;862&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;6. Conclusions&amp;nbsp;and&amp;nbsp;Future&amp;nbsp;Works&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Meerkat&lt;/b&gt;은 &lt;b&gt;오디오-비주얼 입력을 동시에 처리하고 공간적+시간적 세부 정보까지 이해할 수 있는 강력한 multi-modal LLM&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AVOpT 모듈 + AVACE 모듈&lt;/b&gt; -&amp;gt; 시청각 정보에 대한 강력한&amp;nbsp;조합적 이해력(compositional understanding) -&amp;gt; 다양하고 복잡한 멀티모달 과제 처리 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;훈련용 데이터셋 AVFIT, 평가용 벤치마크 MeerkatBench -&amp;gt; 앞으로의&amp;nbsp;AV-LLM&amp;nbsp;연구에&amp;nbsp;표준으로&amp;nbsp;사용될&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;기반을&amp;nbsp;마련&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다양한 downstream task에 대해서 일관되게 SOTA 성능 달성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;향후 연구 방향&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 1) LLM-guided AV Segmentation: LLM 기반의 보다 정밀한 시청각 불할로 발전시킬 예정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 2) Video 확장 및 시간적 과제: 영상을 직접 입력으로 받을 수 있게 하여 video&amp;nbsp;temporal&amp;nbsp;grounding,&amp;nbsp;video&amp;nbsp;summarization&amp;nbsp;등의&amp;nbsp;과제&amp;nbsp;가능하도록&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 3) 대규모&amp;nbsp;Video-centric&amp;nbsp;데이터&amp;nbsp;구축:&amp;nbsp;대규모&amp;nbsp;비디오&amp;nbsp;중심&amp;nbsp;멀티모달&amp;nbsp;데이터셋과&amp;nbsp;복잡한&amp;nbsp;추론(Reasoning)&amp;nbsp;평가&amp;nbsp;벤치마크&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI</category>
      <category>Ai</category>
      <category>AudioVisualAlignment</category>
      <category>AudioVisualLLM</category>
      <category>AVFIT</category>
      <category>FineGrainedGrounding</category>
      <category>largelanguagemodel</category>
      <category>LLM</category>
      <category>meerkat</category>
      <category>MeerkatBench</category>
      <category>multimodallearning</category>
      <author>jungh150c</author>
      <guid isPermaLink="true">https://jungh150c.tistory.com/321</guid>
      <comments>https://jungh150c.tistory.com/321#entry321comment</comments>
      <pubDate>Tue, 18 Nov 2025 12:07:07 +0900</pubDate>
    </item>
    <item>
      <title>[C++] 도미노 (백준 4196번)</title>
      <link>https://jungh150c.tistory.com/320</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1151&quot; data-origin-height=&quot;474&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PBAsH/dJMcaaXW9HZ/uFGR6EM5a1TgUpOZPCyLB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PBAsH/dJMcaaXW9HZ/uFGR6EM5a1TgUpOZPCyLB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PBAsH/dJMcaaXW9HZ/uFGR6EM5a1TgUpOZPCyLB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPBAsH%2FdJMcaaXW9HZ%2FuFGR6EM5a1TgUpOZPCyLB0%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;1151&quot; height=&quot;474&quot; data-origin-width=&quot;1151&quot; data-origin-height=&quot;474&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/4196&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/4196&lt;/a&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;첨엔 그냥 scc 개수를 구해서 틀렸다.&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;그런데 1과 2가 같은 scc이고 3과 4가 같은 scc이면서 2에서 3으로 가는 간선이 있는 경우를 생각해보면, scc 개수는 2이지만 답은 1이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜냐하면 1을 넘어뜨리면 같은 scc인 2도 자연스럽게 넘어지고 따라서 3, 4도 넘어지기 때문이다.&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;따라서 이 문제는 scc를 구한 뒤, in-degree가 0인 (다른 것에 의해서 넘어지지 않는) scc의 개수만을 세야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1763144009846&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;vector&amp;gt;
#include &amp;lt;stack&amp;gt;
using namespace std;

vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; adj1;
vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; adj2;
vector&amp;lt;bool&amp;gt; vst;
stack&amp;lt;int&amp;gt; stk;
vector&amp;lt;int&amp;gt; scc;
int idx;

void dfs1(int cur) {
    vst[cur] = true;
    for (int nxt: adj1[cur]) {
        if (!vst[nxt]) dfs1(nxt);
    }
    stk.push(cur);
}

void dfs2(int cur) {
    vst[cur] = true;
    scc[cur] = idx;
    for (int nxt: adj2[cur]) {
        if (!vst[nxt]) dfs2(nxt);
    }
}

void solve() {
    int n, m;
    cin &amp;gt;&amp;gt; n &amp;gt;&amp;gt; m;

    adj1 = vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt;(n + 1);
    adj2 = vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt;(n + 1);

    for (int i = 0; i &amp;lt; m; i++) {
        int x, y;
        cin &amp;gt;&amp;gt; x &amp;gt;&amp;gt; y;
        adj1[x].push_back(y);
        adj2[y].push_back(x);
    }

    vst = vector&amp;lt;bool&amp;gt;(n + 1, false);
    for (int i = 1; i &amp;lt; n + 1; i++) {
        if (!vst[i]) dfs1(i);
    }

    vst = vector&amp;lt;bool&amp;gt;(n + 1, false);
    scc = vector&amp;lt;int&amp;gt;(n + 1, -1);
    idx = 0;
    while (!stk.empty()) {
        int x = stk.top();
        stk.pop();
        if (!vst[x]) {
            dfs2(x);
            idx++;
        }
    }

    vector&amp;lt;int&amp;gt; sccin(idx, 0);
    for (int cur = 1; cur &amp;lt; n + 1; cur++) {
        for (int nxt: adj1[cur]) {
            if (scc[cur] != scc[nxt]) {
                sccin[scc[nxt]]++;
            }
        }
    }

    int ans = 0;
    for (int i = 0; i &amp;lt; idx; i++) {
        if (sccin[i] == 0) ans++;
    }
    cout &amp;lt;&amp;lt; ans &amp;lt;&amp;lt; '\n';
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int T = 1;
    cin &amp;gt;&amp;gt; T;
    for (int i = 0; i &amp;lt; T; i++) {
        solve();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(AC)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>PS</category>
      <category>C++</category>
      <category>강한 연결 요소</category>
      <category>그래프</category>
      <category>방향 비순환 그래프</category>
      <category>위상 정렬</category>
      <author>jungh150c</author>
      <guid isPermaLink="true">https://jungh150c.tistory.com/320</guid>
      <comments>https://jungh150c.tistory.com/320#entry320comment</comments>
      <pubDate>Sat, 15 Nov 2025 03:17:21 +0900</pubDate>
    </item>
    <item>
      <title>[C++] Strongly Connected Component (백준 2150번) - 강한 연결 요소</title>
      <link>https://jungh150c.tistory.com/319</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1151&quot; data-origin-height=&quot;702&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PZ5ql/dJMcafkEPsg/sKB6TiAQkdDXj8YSmqwMi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PZ5ql/dJMcafkEPsg/sKB6TiAQkdDXj8YSmqwMi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PZ5ql/dJMcafkEPsg/sKB6TiAQkdDXj8YSmqwMi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPZ5ql%2FdJMcafkEPsg%2FsKB6TiAQkdDXj8YSmqwMi0%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;1151&quot; height=&quot;702&quot; data-origin-width=&quot;1151&quot; data-origin-height=&quot;702&quot;/&gt;&lt;/span&gt;&lt;/figure&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;b&gt;강한 연결 요소 - Strongly Connected Component (SCC)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방향 그래프에서 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;모든 정점 쌍 사이에 경로가 존재할 때,&lt;span&gt; 그 그래프는 강하게 연결되어 있다고 한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;방향 그래프에서 모든 정점 쌍 사이에 경로가 존재하는 최대 부분 그래프를 강한 연결 요소라고 한다.&lt;/span&gt;&lt;/span&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;b&gt;Kosaraju 알고리즘: scc를 구하는 알고리즘&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;adj1: 원래&amp;nbsp;방향&amp;nbsp;그래프의&amp;nbsp;인접&amp;nbsp;리스트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;adj2: 원래&amp;nbsp;그래프의&amp;nbsp;간선을&amp;nbsp;모두&amp;nbsp;반대로&amp;nbsp;뒤집은&amp;nbsp;그래프의&amp;nbsp;인접&amp;nbsp;리스트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dfs1: 원래 그래프를 dfs로 탐색함. 탐색하면서 완료 정점을 stack에 담음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dfs2: stack의 정점들을 pop하면서 반전 그래프를 dfs로 탐색함. =&amp;gt; dfs2 호출 횟수가 강한 연결 요소 개수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1763140698923&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;vector&amp;gt;
#include &amp;lt;stack&amp;gt;
#include &amp;lt;algorithm&amp;gt;
using namespace std;

int v, e;
vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; adj1;
vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; adj2;
vector&amp;lt;bool&amp;gt; vst;
stack&amp;lt;int&amp;gt; stk;
vector&amp;lt;int&amp;gt; tmp;

void dfs1(int cur) {
    vst[cur] = true;
    for (int nxt: adj1[cur]) {
        if (!vst[nxt]) dfs1(nxt);
    }
    stk.push(cur);
}

void dfs2(int cur) {
    vst[cur] = true;
    tmp.push_back(cur);
    for (int nxt: adj2[cur]) {
        if (!vst[nxt]) dfs2(nxt);
    }
}

void solve() {
    cin &amp;gt;&amp;gt; v &amp;gt;&amp;gt; e;

    adj1 = vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt;(v + 1);
    adj2 = vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt;(v + 1);

    for (int i = 0; i &amp;lt; e; i++) {
        int a, b;
        cin &amp;gt;&amp;gt; a &amp;gt;&amp;gt; b;
        adj1[a].push_back(b);
        adj2[b].push_back(a);
    }

    vst = vector&amp;lt;bool&amp;gt;(v + 1, false);
    for (int i = 1; i &amp;lt; v + 1; i++) {
        if (!vst[i]) dfs1(i);
    }

    vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; ans;
    vst = vector&amp;lt;bool&amp;gt;(v + 1, false);
    while (!stk.empty()) {
        int x = stk.top();
        stk.pop();
        if (!vst[x]) {
            tmp = vector&amp;lt;int&amp;gt;();
            dfs2(x);
            ans.push_back(tmp);
        }
    }

    for (int i = 0; i &amp;lt; ans.size(); i++) {
        sort(ans[i].begin(), ans[i].end());
    }
    sort(ans.begin(), ans.end());

    cout &amp;lt;&amp;lt; ans.size() &amp;lt;&amp;lt; '\n';
    for (int i = 0; i &amp;lt; ans.size(); i++) {
        for (int x: ans[i]) cout &amp;lt;&amp;lt; x &amp;lt;&amp;lt; ' ';
        cout &amp;lt;&amp;lt; &quot;-1\n&quot;;
    }
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int T = 1;
    for (int i = 0; i &amp;lt; T; i++) {
        solve();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(AC)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>PS</category>
      <category>C++</category>
      <category>강한 연결 요소</category>
      <category>그래프</category>
      <author>jungh150c</author>
      <guid isPermaLink="true">https://jungh150c.tistory.com/319</guid>
      <comments>https://jungh150c.tistory.com/319#entry319comment</comments>
      <pubDate>Sat, 15 Nov 2025 02:23:51 +0900</pubDate>
    </item>
    <item>
      <title>[C++] 단방향 링크 네트워크 (백준 3295번)</title>
      <link>https://jungh150c.tistory.com/318</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1154&quot; data-origin-height=&quot;847&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bN64I4/dJMcafkENNS/o3SKYcgbrTTUYOwE5dSGh1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bN64I4/dJMcafkENNS/o3SKYcgbrTTUYOwE5dSGh1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bN64I4/dJMcafkENNS/o3SKYcgbrTTUYOwE5dSGh1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbN64I4%2FdJMcafkENNS%2Fo3SKYcgbrTTUYOwE5dSGh1%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;1154&quot; height=&quot;847&quot; data-origin-width=&quot;1154&quot; data-origin-height=&quot;847&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1150&quot; data-origin-height=&quot;299&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/W6pUV/dJMcabJkmN1/ytETk5HzPI5kbsqwJwdKv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/W6pUV/dJMcabJkmN1/ytETk5HzPI5kbsqwJwdKv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/W6pUV/dJMcabJkmN1/ytETk5HzPI5kbsqwJwdKv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FW6pUV%2FdJMcabJkmN1%2FytETk5HzPI5kbsqwJwdKv1%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;1150&quot; height=&quot;299&quot; data-origin-width=&quot;1150&quot; data-origin-height=&quot;299&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/3295&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/3295&lt;/a&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;b&gt;그래프를 이루는 각 노드들의 in-degree도 최대 1이고 out-degree도 최대 1&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;그리고 k개의 노드로 이루어진 링의 가치가 k이고 k개의 노드로 이루어진 선형 배열의 가치가 k라는 것은 &lt;b&gt;어떤 그래프에서 각 노드의 in-degree도 최대 1이고 out-degree도 최대 1이 되도록 간선들을 선택했을 때&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;p data-ke-size=&quot;size16&quot;&gt;따라서 왼쪽에 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;출발&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; 노드 집합을 두고 오른쪽에 도착 노드 집합을 두고 최대 이분 매칭을 구하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1763136250620&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Reference: green55 teamnote
// https://github.com/green5555/Teamnote/blob/master/TeamNote/BiMatch.cpp

#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;

const int MAX = 2000;
struct BiMatching {
    vector&amp;lt;int&amp;gt; adj[MAX+5];
    int iter, A[MAX+5], B[MAX+5], was[MAX+5];

    bool dfs(int u) {
        was[u] = iter;
        for (int v : adj[u]) {
            if (B[v] == -1) {
                A[u] = v;
                B[v] = u;
                return true;
            }
        }
        for (int v : adj[u]) {
            if (was[B[v]] != iter &amp;amp;&amp;amp; dfs(B[v])) {
                A[u] = v;
                B[v] = u;
                return true;
            }
        }
        return false;
    }

    int biMatch(int n=MAX) {
        fill(A, A+n, -1);
        fill(B, B+n, -1);
        fill(was, was+n, 0);
        iter = 0;
        int res = 0;
        while (true) {
            iter++;
            int add = 0;
            for (int i = 0; i &amp;lt; n; i++) {
                if (A[i] == -1 &amp;amp;&amp;amp; dfs(i)) {
                    add++;
                }
            }
            if (add == 0) {
                break;
            }
            res += add;
        }
        return res;
    }
};

void solve() {
    BiMatching bm;

    int n, m;
    cin &amp;gt;&amp;gt; n &amp;gt;&amp;gt; m;

    while (m--) {
        int a, b;
        cin &amp;gt;&amp;gt; a &amp;gt;&amp;gt; b;
        bm.adj[a].push_back(b + 1000);
    }

    cout &amp;lt;&amp;lt; bm.biMatch() &amp;lt;&amp;lt; '\n';
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int T = 1;
    cin &amp;gt;&amp;gt; T;
    for (int i = 0; i &amp;lt; T; i++) {
        solve();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(AC)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>PS</category>
      <category>C++</category>
      <category>이분 매칭</category>
      <author>jungh150c</author>
      <guid isPermaLink="true">https://jungh150c.tistory.com/318</guid>
      <comments>https://jungh150c.tistory.com/318#entry318comment</comments>
      <pubDate>Sat, 15 Nov 2025 01:18:16 +0900</pubDate>
    </item>
    <item>
      <title>[C++] 돌멩이 제거 (백준 1867번)</title>
      <link>https://jungh150c.tistory.com/317</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2025&quot; data-origin-height=&quot;873&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y8tWJ/dJMcafSt1u6/GlUXhK6Ap4gKbS6rfqO6T0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y8tWJ/dJMcafSt1u6/GlUXhK6Ap4gKbS6rfqO6T0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y8tWJ/dJMcafSt1u6/GlUXhK6Ap4gKbS6rfqO6T0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy8tWJ%2FdJMcafSt1u6%2FGlUXhK6Ap4gKbS6rfqO6T0%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;2025&quot; height=&quot;873&quot; data-origin-width=&quot;2025&quot; data-origin-height=&quot;873&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1867&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1867&lt;/a&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;&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;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 &lt;b&gt;모든 돌(간선)을 커버하기 위해 필요한 최소 정점 수&lt;/b&gt;는 &lt;b&gt;이분 그래프에서의 최소 정점 커버 (Minimum Vertex Cover) 문제&lt;/b&gt;이며, 쾨니그&amp;nbsp;정리에&amp;nbsp;의해&amp;nbsp;이는&amp;nbsp;&lt;b&gt;최대&amp;nbsp;이분&amp;nbsp;매칭의&amp;nbsp;크기&lt;/b&gt;와 같다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1763002754642&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Reference: green55 teamnote
// https://github.com/green5555/Teamnote/blob/master/TeamNote/BiMatch.cpp

#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;

const int MAX = 1001;
struct BiMatching {
    vector&amp;lt;int&amp;gt; adj[MAX+5];
    int iter, A[MAX+5], B[MAX+5], was[MAX+5];

    bool dfs(int u) {
        was[u] = iter;
        for (int v : adj[u]) {
            if (B[v] == -1) {
                A[u] = v;
                B[v] = u;
                return true;
            }
        }
        for (int v : adj[u]) {
            if (was[B[v]] != iter &amp;amp;&amp;amp; dfs(B[v])) {
                A[u] = v;
                B[v] = u;
                return true;
            }
        }
        return false;
    }

    int biMatch(int n=MAX) {
        fill(A, A+n, -1);
        fill(B, B+n, -1);
        fill(was, was+n, 0);
        iter = 0;
        int res = 0;
        while (true) {
            iter++;
            int add = 0;
            for (int i = 0; i &amp;lt; n; i++) {
                if (A[i] == -1 &amp;amp;&amp;amp; dfs(i)) {
                    add++;
                }
            }
            if (add == 0) {
                break;
            }
            res += add;
        }
        return res;
    }
};

void solve() {
    BiMatching bm;

    int n, k;
    cin &amp;gt;&amp;gt; n &amp;gt;&amp;gt; k;

    while (k--) {
        int r, c;
        cin &amp;gt;&amp;gt; r &amp;gt;&amp;gt; c;
        bm.adj[r].push_back(c + 500);
    }

    cout &amp;lt;&amp;lt; bm.biMatch() &amp;lt;&amp;lt; '\n';
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int T = 1;
    for (int i = 0; i &amp;lt; T; i++) {
        solve();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(AC)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>PS</category>
      <category>C++</category>
      <category>이분 매칭</category>
      <author>jungh150c</author>
      <guid isPermaLink="true">https://jungh150c.tistory.com/317</guid>
      <comments>https://jungh150c.tistory.com/317#entry317comment</comments>
      <pubDate>Thu, 13 Nov 2025 11:59:31 +0900</pubDate>
    </item>
  </channel>
</rss>