[c++] BOJ 19535 :: γ„·γ„·γ„·γ…ˆ


λ‚œμ΄λ„ : κ³¨λ“œ 3

 

문제

γ„·γ„·γ„·γ…ˆ 문제 λ°”λ‘œκ°€κΈ°

정점이 λ„€ 개 이상 μžˆλŠ” μž„μ˜μ˜ νŠΈλ¦¬μ— λŒ€ν•΄, κ·Έ νŠΈλ¦¬μ—μ„œ 정점 λ„€ 개둜 이루어진 집합을 κ³ λ₯΄μž. 전체 트리의 κ°„μ„ λ“€ 쀑 집합에 μ†ν•œ 두 정점을 μž‡λŠ” κ°„μ„ λ§Œμ„ 남겼을 λ•Œ, λ„€ 개의 정점이 ν•˜λ‚˜μ˜ 트리 ν˜•νƒœλ‘œ μ΄μ–΄μ§€κ²Œ λœλ‹€λ©΄ ‘γ„·’ λͺ¨μ–‘μ΄κ±°λ‚˜ ‘γ…ˆ’ λͺ¨μ–‘일 것이닀. νŠΈλ¦¬μ—μ„œ ‘γ„·’의 κ°œμˆ˜μ™€ ‘γ…ˆ’의 개수λ₯Ό 각각 νŠΈλ¦¬μ—μ„œ ‘γ„·’ λͺ¨μ–‘, ‘γ…ˆ’ λͺ¨μ–‘을 μ΄λ£¨λŠ” 정점 λ„€ 개짜리 μ§‘ν•©μ˜ 개수라고 ν•˜μž.

이제, λ™ν˜„μ΄λŠ” μ„Έμƒμ˜ λͺ¨λ“  트리λ₯Ό λ‹€μŒκ³Ό 같은 μ„Έ μ’…λ₯˜λ‘œ λ‚˜λˆ„μ—ˆλ‹€.

  • D-트리 : ‘γ„·’이 ‘γ…ˆ’의 3배보닀 λ§Žμ€ 트리
  • G-트리 : ‘γ„·’이 ‘γ…ˆ’의 3배보닀 적은 트리
  • DUDUDUNGA-트리 : ‘γ„·’이 ‘γ…ˆ’의 μ •ν™•νžˆ 3배만큼 μžˆλŠ” 트리

신이 λ‚œ λ™ν˜„μ΄λŠ” 트리만 보이면 κ·Έ νŠΈλ¦¬μ— μžˆλŠ” ‘γ„·’κ³Ό ‘γ…ˆ’이 λͺ‡ κ°œμΈμ§€ μ„Έκ³  λ‹€λ‹ˆκΈ° μ‹œμž‘ν–ˆλ‹€. ν•˜μ§€λ§Œ 곧 정점이 30만 κ°œλ‚˜ μžˆλŠ” νŠΈλ¦¬κ°€ λ™ν˜„μ΄ μ•žμ— λ‚˜νƒ€λ‚¬κ³ , λ™ν˜„μ΄λŠ” 그만 정신을 μžƒκ³  λ§μ•˜λ‹€. λ™ν˜„μ΄λ₯Ό λŒ€μ‹ ν•΄ 주어진 νŠΈλ¦¬κ°€ D-νŠΈλ¦¬μΈμ§€ G-νŠΈλ¦¬μΈμ§€ μ•„λ‹ˆλ©΄ DUDUDUNGA-νŠΈλ¦¬μΈμ§€ μ•Œλ €μ£Όμž!

 

풀이

  • γ…ˆμ€ 간선이 3개 이상인 λ…Έλ“œμ—μ„œ λ‚˜νƒ€λ‚œλ‹€.
    • 간선이 n개 일 λ•Œ, 3개만 κ³ λ₯΄λŠ” 경우의 수만큼 γ…ˆκ°€ λ‚˜νƒ€λ‚˜λ―€λ‘œ
    • γ…ˆλŠ” nC3인 (n)(n-1)(n-3)/6 개 만큼 λ‚˜μ˜¬ 수 μžˆλ‹€.

  • ㄷ은 간선이 2개인 λ…Έλ“œκ°€ 2개 μ—°μ†ν•΄μ„œ λ“±μž₯ν•˜κ³  각각 μ—°κ²°λœ λ‹€λ₯Έ λ…Έλ“œκ°€ 있으면 λ‚˜νƒ€λ‚œλ‹€.
    • ?-n-m-? ꡬ쑰일 λ•Œ, ㄷ은 (n-1)*(m-1) 개 만큼 λ‚˜μ˜¬ 수 μžˆλ‹€.

 

μ½”λ“œ

#include <iostream>
#include <vector>
#include <string>

using namespace std;

long long int dNum = 0; long long int gNum = 0;
vector<int> visited(300005, 0);

void calTree(vector<vector<int>>& tree, int node, int currD) {
    visited[node] = 1;
    int linkSize = tree[node].size();
    if (linkSize >= 3) {
        gNum += linkSize * (linkSize - 1) * (linkSize - 2) / 6; // 이뢀뢄을 생각 λͺ»ν•΄μ”€!
    }
    if (linkSize >= 2) {
        if (currD != 0) {
            dNum += currD * (linkSize - 1);
        }
    }
    currD = linkSize - 1;
    for (int i = 0; i < linkSize; i++) {
        int nextNode = tree[node][i];
        if (visited[nextNode] != 0)
            continue;
        calTree(tree, nextNode, currD);
    }
}

string returnTreeType() {
    if (dNum > gNum * 3) {
        return "D";
    }
    else if (dNum < gNum * 3) {
        return "G";
    }
    else {
        return "DUDUDUNGA";
    }
}

int main() {
    // γ…ˆ => μ—°κ²°λœ λ…Έλ“œκ°€ n개인 λ…Έλ“œμ—μ„œ γ…ˆ (n)(n-1)(n-3)/6개
    // γ„· => μ—°κ²°λœ λ…Έλ“œκ°€ 2개 이상인 λ…Έλ“œ μ˜†μ— 또 2개 이상이 λ…Έλ“œκ°€ μžˆμ„ λ•Œ => κ°μžμ—κ²Œ μ—°κ²°λœ λ…Έλ“œ 수의 곱만큼 ㄷ이 λ‚˜μ˜΄
    // n : 10^6

    int N; cin >> N;
    vector<vector<int>> tree(N + 1, vector<int>()); // ν•΄λ‹Ή λ…Έλ“œμ™€ μ—°κ²°λœ λ…Έλ“œμ˜ idx
    for (int i = 0; i < N-1; i++) {
        int s, e; cin >> s >> e;
        tree[s].push_back(e);
        tree[e].push_back(s);
    }

    calTree(tree, 1, 0);
    cout << returnTreeType();
}

 

 

κ²°κ³Ό

아이디 λ©”λͺ¨λ¦¬ μ‹œκ°„ μ½”λ“œ 길이
gmldms784 38196 460 1317
λ°˜μ‘ν˜•