Back to : algorithms
Contents

ํ’€์ด

๋ฌธ์ œ ํ•ด์„

๋ฒˆ์—ญ์ด ์ƒ๋‹นํžˆ ๋‚œํ•ดํ•˜๊ฒŒ ์ž‘์„ฑ๋˜์–ด ์žˆ๋‹ค. ์š”์ ์„ ์ •๋ฆฌํ•˜์ž๋ฉด

  • ๋ฃจํŠธ ์žˆ๋Š” ํŠธ๋ฆฌ๊ฐ€ ์ฃผ์–ด์ง„๋‹ค.
  • ๊ฐ ๋…ธ๋“œ์—๋Š” $L_i, C_i$ ๊ฐ’์ด ์ฃผ์–ด์ง„๋‹ค.
  • ํŠธ๋ฆฌ์˜ ์–ด๋–ค ๋…ธ๋“œ ํ•˜๋‚˜ (๋งค๋‹ˆ์ €) ๋ฅผ ๊ณ ๋ฅธ๋‹ค.
  • ๊ทธ ํŠธ๋ฆฌ๋ฅผ ๋ฃจํŠธ๋กœ ํ•˜๋Š” ์„œ๋ธŒํŠธ๋ฆฌ์—์„œ ๋ช‡ ๊ฐœ์˜ ๋…ธ๋“œ(๋‹Œ์ž)๋ฅผ ๊ณ ๋ฅธ๋‹ค. ๋งค๋‹ˆ์ €๋ฅผ ๋‹Œ์ž๋กœ ์‚ผ์„ ์ˆ˜ ์žˆ๋‹ค.
  • ์ด๋•Œ, ๊ณ ๋ฅธ ๋‹Œ์ž (๋งค๋‹ˆ์ €๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๋Š”๋‹ค) ์˜ $C_i$ ๊ฐ’์˜ ํ•ฉ์ด $M$์„ ๋„˜์–ด์„œ๋Š” ์•ˆ ๋œ๋‹ค.
  • ๋‚˜์˜ ์ ์ˆ˜ ๋Š”, (๋งค๋‹ˆ์ €์˜ $L$ ๊ฐ’) * (๊ณ ๋ฅธ ๋‹Œ์ž์˜ ์ˆ˜) ๋กœ ์ •์˜๋œ๋‹ค.
  • ์ ์ˆ˜๋ฅผ ์ตœ๋Œ€ํ™”ํ•˜๋ผ.

Algorithm

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์•ฝ๊ฐ„ Naiveํ•œ ์†”๋ฃจ์…˜์„ ์ƒ๊ฐํ•ด ๋ณด์ž. ๊ฐ ๋…ธ๋“œ๋งˆ๋‹ค, ๋‚ด๊ฐ€ ๋งค๋‹ˆ์ €์ผ ๋•Œ ๊ณ ๋ฅด๋Š” ์ตœ์„ ์˜ ๋‹Œ์ž ์กฐํ•ฉ ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ž. ๋‚ด๊ฐ€ ๋งค๋‹ˆ์ €์ผ ๋•Œ๋Š” ๋‚˜์˜ ์„œ๋ธŒํŠธ๋ฆฌ์—์„œ ๋‹Œ์ž๋“ค์„ ๊ณจ๋ผ์•ผ ํ•˜๊ณ , ์ด๋•Œ ๊ฐ ๋‹Œ์ž๋Š” ๋ชจ๋‘ ๋˜‘๊ฐ™์ด ์ทจ๊ธ‰๋˜๋ฏ€๋กœ ๋ฌด์กฐ๊ฑด ์›”๊ธ‰ $C_i$ ๊ฐ€ ๋‚ฎ์€ ๊ฐ’์‹ผ ๋‹Œ์ž๋ฅผ ๋งŽ์ด ๋ฐฐ์น˜ํ• ์ˆ˜๋ก ์ด๋“์ด๋‹ค. ์ด ๋ฐฐ์น˜๋ฅผ ๋ฆฌํ”„ ๋…ธ๋“œ๋ถ€ํ„ฐ ๊ฐฑ์‹ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ž. ์ด๋•Œ, ๋‹Œ์ž $x$์— ๋Œ€ํ•œ ์ตœ์„ ๋‹Œ์ž์กฐํ•ฉ์„ $S_x$ ๋ผ๋Š” ์ง‘ํ•ฉ์œผ๋กœ ์ •์˜ํ•˜์ž.

๊ด€์ฐฐ $x$์˜ ancestor node $p$์— ๋Œ€ํ•ด, $S_x$์— ํฌํ•จ๋˜์ง€ ์•Š๋Š” ๋…ธ๋“œ๋Š” $S_p$์— ํฌํ•จ๋˜์ง€ ์•Š๋Š”๋‹ค.

์ฆ๋ช… $S_p$๋ฅผ ์–ด๋–ป๊ฒŒ ๋งŒ๋“ค์ง€ ์ƒ๊ฐํ•ด ๋ณด์ž. ๋จผ์ €, $S_p$๋ฅผ ๋งŒ๋“œ๋Š” ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๋Š”, ์ž๊ธฐ ์ž์‹ ๋…ธ๋“œ $v_1, \dots v_k$ ์— ๋Œ€ํ•ด $S_{v_i}$ ๋“ค์„ ๋ชจ๋‘ ํ•ฉ์ง‘ํ•ฉํ•œ ๋‹ค์Œ, ๋น„์šฉ์ด $M$๋ณด๋‹ค ์ž‘๊ฑฐ๋‚˜ ๊ฐ™์•„์งˆ ๋•Œ๊นŒ์ง€ ๋น„์‹ผ ๋‹Œ์ž๋ฅผ ๊ณ„์† ์ž๋ฅด๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์ด ์˜ฌ๋ฐ”๋ฅธ $S_p$๋ฅผ ๋ณด์žฅํ•จ์€ ์–ด๋ ต์ง€ ์•Š๊ฒŒ ๋ณด์—ฌ์ง„๋‹ค.

์ด ๊ด€์ฐฐ๋กœ๋ถ€ํ„ฐ ์–ป์–ด์ง€๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ์ƒ๊ฐํ•ด ๋ณด์ž. ๊ฐ ๋…ธ๋“œ๋งˆ๋‹ค, ์ž๊ธฐ ์ž์‹ ๋…ธ๋“œ์˜ ๋ชจ๋“  set์„ ํ•ฉ์ณ์•ผ ํ•˜๊ณ , ํ•„์š”ํ•˜๋‹ค๋ฉด ๋‹Œ์ž๋“ค์„ ํ•ด๊ณ ํ•ด์•ผ ํ•œ๋‹ค. ์ด๋•Œ $S_x$๋ฅผ set์ด๋‚˜ priority queue์™€ ๊ฐ™์€ ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ด€๋ฆฌํ•œ๋‹ค๋ฉด, ์ตœ๋Œ€ $n$๋ฒˆ ํ•ฉ์ง‘ํ•ฉ ์—ฐ์‚ฐ์„ ํ•ด์•ผ ํ•˜๋ฉฐ, ๊ฐ ์ง‘ํ•ฉ์˜ ํฌ๊ธฐ๊ฐ€ ์ตœ๋Œ€ $n$๊นŒ์ง€ ๊ฐˆ ์ˆ˜ ์žˆ๊ณ , ์›์†Œ ํ•˜๋‚˜๋ฅผ ์›€์ง์ด๋Š” ๋ฐ $O(\log n)$ ์‹œ๊ฐ„์ด ๋“ค ๊ฒƒ์ด๋ฏ€๋กœ $O(n^2 \log n)$ ์‹œ๊ฐ„์ด ์†Œ์š”๋œ๋‹ค.

Merge sort tree๋ฅผ ๋งŒ๋“œ๋Š” ๋•Œ์™€ ๋น„์Šทํ•˜๊ฒŒ, set์„ ์“ฐ์ง€ ์•Š๊ณ  vector ๊ฐ™์€๊ฒƒ์„ ์ •๋ ฌํ•ด์„œ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉด์„œ mergeํ•˜๋ฉด $O(n^2)$ ์‹œ๊ฐ„์—๋„ ์–ด๋–ป๊ฒŒ ๊ฐ€๋Šฅํ•  ๊ฒƒ ๊ฐ™๊ธฐ๋„ ํ•˜๋‹ค. ์ด ๋ฐฉ๋ฒ•์€ ๊ตฌํ˜„ํ•ด ๋ณด์ง€ ์•Š์•„์„œ ๋ณต์žก๋„์—๋Š” ์ž์‹ ์ด ์—†๋‹ค.

Small-to-Large Technique

์•„์ฃผ ์ž‘์€ ๋ถ€๋ถ„์„ ๋ฐ”๊ฟˆ์œผ๋กœ์จ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ์ค„์ด๋Š” ํ…Œํฌ๋‹‰์ธ๋ฐ, ๊ต‰์žฅํžˆ ์•„๋ฆ„๋‹ต๋‹ค. ์š”์ง€๋Š”, ์œ„ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๊ทธ๋Œ€๋กœ ์ˆ˜ํ–‰ํ•˜๋˜, set์„ ํ•ฉ์น  ๋•Œ ํ•ญ์ƒ ์ž‘์€ ์ง‘ํ•ฉ์— ์žˆ๋Š” ์›์†Œ๋“ค์„ ํฐ ์ง‘ํ•ฉ์œผ๋กœ ์˜ฎ๊ธฐ๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ๋งŒ ํ•ฉ์น˜๋Š” ๊ฒƒ์ด๋‹ค. ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ํ•ฉ์น  ๋–„๋Š” ๊ฐ€์žฅ ํฐ ๊ฒƒ์„ ๊ธฐ์ค€์œผ๋กœ ๋‚˜๋จธ์ง€๋ฅผ ๊ฑฐ๊ธฐ์— ์ง‘์–ด๋„ฃ๊ธฐ๋กœ ํ•˜์ž.

์ด ๋ฐฉ๋ฒ•์ด ๋ณต์žก๋„๋ฅผ ์ค„์—ฌ ์คŒ์„ ์ฆ๋ช…ํ•˜์ž.


์ฆ๋ช… ๊ฐ ๋‹Œ์ž $x$๋งˆ๋‹ค, $x$๊ฐ€ ํฌํ•จ๋œ ์ง‘ํ•ฉ์ด ์žˆ์„ ๊ฒƒ์ด๋‹ค. (์ง‘ํ•ฉ์—์„œ ํ•œ ๋ฒˆ ๋น ์ง„ ๋‹Œ์ž๋Š” ์‚ฌ๋ผ์ง€๋Š” ๊ฒƒ์ด๋ฏ€๋กœ, ๊ทธ๊ฑธ ์ƒˆ๋กœ์šด ์ง‘ํ•ฉ์ฒ˜๋Ÿผ ์ƒ๊ฐํ•˜์ž) ์œ„ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์ˆ˜ํ–‰ ๊ณผ์ •์„ ์†์œผ๋กœ ๊ทธ๋ ค ๋ณด๋ฉด, ๊ฐ ์›์†Œ๋งˆ๋‹ค ๋ชจ๋“  ์ง‘ํ•ฉ๋“ค์„ ํ†ตํ‹€์–ด ํ•œ ๋ฒˆ๋งŒ ์žˆ์œผ๋ฉด ๋œ๋‹ค (๋‹ค ๊ณ„์‚ฐํ•œ ๋‹ค์Œ ์ž์‹ ๋…ธ๋“œ์˜ $S_v$ ๋“ค์„ ๋ชจ๋‘ ์ง€์›Œ๋ฒ„๋ ค๋„ ๋˜๋ฏ€๋กœ).
๋”ฐ๋ผ์„œ, $x$๊ฐ€ ํฌํ•จ๋œ ์ง‘ํ•ฉ $T(x)$ ๋ฅผ ํ•ญ์ƒ identify ํ•  ์ˆ˜ ์žˆ๋‹ค.
์ด๋•Œ, $T(x)$์˜ ํฌ๊ธฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜ $f(x)$๋ฅผ ์ƒ๊ฐํ•˜์ž. $f(x)$๋Š”, ์ฆ‰, ์ง€๊ธˆ ์ด ์ˆœ๊ฐ„ x๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋Š” ์ง‘ํ•ฉ์˜ ํฌ๊ธฐ ๋ผ๊ณ  ์ •์˜ํ•œ๋‹ค. ์›์†Œ $x$๊ฐ€ ์–ด๋–ค ์ง‘ํ•ฉ $A$์—์„œ ๋‹ค๋ฅธ ์ง‘ํ•ฉ $B$๋กœ ์ด๋™ํ•œ๋‹ค๋ฉด, ์ฆ‰ $T(x)$๊ฐ€ $A$์—์„œ $B$๋กœ ๋ณ€๊ฒฝ๋œ๋‹ค๋ฉด ์–ด๋–ค ์ผ์ด ์ผ์–ด๋‚˜๋Š”์ง€ ์ƒ๊ฐํ•ด ๋ณด์ž. ๋งŒ์•ฝ $A$๊ฐ€ $B$๋ณด๋‹ค ์ž‘์•˜๋‹ค๋ฉด, $x$ ํ•˜๋‚˜๋งŒ ์˜ฎ๊ธฐ๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ $A$๋ฅผ ํ†ต์งธ๋กœ ๋“ค์–ด๋‹ค๊ฐ€ $B$๋กœ ์˜ฎ๊ธธ ๋•Œ๋ง $x$๊ฐ€ ์›€์ง์ด๋ฏ€๋กœ $T(x)$๋Š” $\abs{A}$์—์„œ $\abs{A} + \abs{B}$๋กœ ๋ฐ”๋€Œ๊ฒŒ ๋˜์–ด, ์ ์–ด๋„ 2๋ฐฐ ์ด์ƒ ๋Š˜์–ด๋‚œ๋‹ค. ๋ฐ˜๋ฉด ๋งŒ์•ฝ $A$๊ฐ€ $B$๋ณด๋‹ค ์ปธ๋‹ค๋ฉด, $A$์™€ $B$๋ฅผ ํ•ฉ์น˜๋”๋ผ๋„ $x$๋Š” ์›€์ง์ด์ง€ ์•Š๊ณ  $B$์— ์žˆ์—ˆ๋˜ ์›์†Œ๋“ค์ด ์ด์ชฝ์œผ๋กœ ์›€์ง์ผ ๊ฒƒ์ด๋‹ค. ์ฆ‰, $x$๋ฅผ relocate ํ•˜๋Š” ์—ฐ์‚ฐ์ด ์ผ์–ด๋‚œ๋‹ค๋ฉด ๋ฐ˜๋“œ์‹œ $f(x)$๊ฐ€ 2๋ฐฐ ์ด์ƒ ์ฆ๊ฐ€ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

์ด๋•Œ, ๋‹น์—ฐํ•˜์ง€๋งŒ ์ค‘์š”ํ•œ ์‚ฌ์‹ค์€ ๋‹น์—ฐํžˆ $f(x)$๋Š” $n$์„ ๋„˜์„ ์ˆ˜ ์—†๋‹ค๋Š” ์ ์ด๋‹ค. ๋”ฐ๋ผ์„œ, ์ด ์‚ฌ์‹ค๋“ค์„ ์ข…ํ•ฉํ•˜๋ฉด, $x$๋Š” ์ตœ๋Œ€ $O(\log n)$ ๋ฒˆ๋งŒ ์ด๋™ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.


๋”ฐ๋ผ์„œ, ์ด ํ…Œํฌ๋‹‰์„ ์ ์šฉํ•˜๋ฉด, ๋ชจ๋“  ์›์†Œ๋Š” ์ตœ๋Œ€ $O(\log n)$ ๋ฒˆ ์›€์ง์ด๊ณ , ์›€์ง์ผ๋•Œ๋งˆ๋‹ค $O(\log n)$ ์‹œ๊ฐ„์ด ์†Œ๋ชจ๋˜๋ฏ€๋กœ ์ „์ฒด ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๊ฐ€ $O(n \log^2 n)$์œผ๋กœ ํฌ๊ฒŒ ์ค„์–ด๋“ ๋‹ค. ์ด ํ…Œํฌ๋‹‰์„ smaller-to-larger ๊ฐ™์€ ์ด๋ฆ„์œผ๋กœ ๋ถ€๋ฅด๊ธฐ๋„ ํ•˜๋Š”๋ฐ, ์š”์ ์€ ์•ฝ๊ฐ„ DSU์—์„œ union by size ํ•  ๋•Œ ๋ณต์žก๋„ ์ฆ๋ช…ํ•  ๋•Œ์™€ ๊ฐ™๋‹ค.

๊ตฌํ˜„๋„ ๊ต‰์žฅํžˆ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฝ”๋“œ

#include <bits/stdc++.h>
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#define ll long long
#define int ll
#define eps 1e-7
#define all(x) ((x).begin()),((x).end())
#define usecppio ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;
using pii = pair<int, int>;

struct PQueue
{
    priority_queue <int> pq;
    int total = 0;
    void push(int x)
    {
        pq.push(x);
        total += x;
    }
    int peek() {return pq.top();}
    int pop()
    {
        int x = pq.top();
        total -= x;
        pq.pop();
        return x;
    }
    int size() {return (int)(pq.size());}
    bool empty() {return pq.empty();}
};

void merge(PQueue &dest, PQueue &src)
{
    if (dest.size() < src.size())
        swap(dest, src);
    while (!src.empty())
        dest.push(src.pop());
}

int n, m, ans;
vector <int> T[101010];
vector <PQueue> PQS(101010);
int lead[101010], cost[101010];

void dfs(int r, int p)
{
    PQS[r].push(cost[r]);
    for (int c : T[r])
        if (c != p)
            dfs(c, r);
    for (int c : T[r])
        if (c != p)
            merge(PQS[r], PQS[c]);
    while (PQS[r].total > m)
        PQS[r].pop();
    ans = max(ans, lead[r] * PQS[r].size());
}

int32_t main()
{
    usecppio
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        int b, c, l; cin >> b >> c >> l;
        T[b].push_back(i);
        T[i].push_back(b);
        lead[i] = l;
        cost[i] = c;
    }
    cost[0] = INT_MAX;
    dfs(0, -1);
    cout << ans << '\n';
}