문제 설명

1. 문제 링크

http://icpc.me/17831

 

17831번: 대기업 승범이네

첫 번째 줄에 판매원들의 수 N(2 ≤ N ≤ 200,000)이 주어진다. 판매원들은 1번, 2번, …, N번으로 번호가 매겨지며, 승범이는 항상 1번이다. 두 번째 줄에 2번 판매원부터 N번 판매원의 사수가 순서대

www.acmicpc.net

2. 풀이

트리에서 dp를 통해 풀 수 있다.

dp[i][0] : 노드 i가 멘티가 아닐 때, 최댓값

dp[i][1] : 노드 i가 멘티일 때, 최댓값이라 하자.

dp[i][0] = max(dp[i의 자식 노드][0], dp[i의 자신노드][1] + cost[i] * cost[i의 자식노드)의 총합 (이때, 멘티는 최대 1명만 선택 가능)

dp[i][1] = dp[i의 자식 노드][0]의 총 합

멘티를 한명 이하로만 선택하는 구현을 하기 위해 멘티가 i번째를 멘티로 할 때, (멘티가 하나도 없는 모든 자식 합) - (i가 멘티가 아닐 경우) + (i가 멘티일 경우)를 확인하며 구현한다.

3. 코드

#include <iostream>
#include <cstring>
#include <vector>

using namespace std;

const int N = 2e5 + 5;
int cost[N];
int dp[N][2];
vector<int> v[N];

int dpf(int cur, int menti) {
    int &ret = dp[cur][menti];
    if (~ret) return ret;
    ret = 0;
    int noMenti = 0;
    if (!menti) {
        for (auto nxt : v[cur]) noMenti += dpf(nxt, 0);
        ret = noMenti;
        for (auto nxt : v[cur]) {
            ret = max(ret, noMenti - dpf(nxt, 0) + dpf(nxt, 1) + cost[cur] * cost[nxt]);
        }
    } else {
        for (auto nxt : v[cur]) ret += dpf(nxt, 0);
    }
    return ret;
}

int main() {
    int n; cin >> n;
    for (int i = 2; i <= n; i++) {
        int ipt; cin >> ipt;
        v[ipt].push_back(i);
    }
    for (int i = 1; i <= n; i++) cin >> cost[i];
    memset(dp, -1, sizeof dp);
    cout << dpf(1, 0);
}

'Algorithm > BOJ' 카테고리의 다른 글

백준[16927] 배열 돌리기 2  (0) 2021.11.16
백준[5446] 용량 부족  (0) 2021.11.16
백준[19581] 두 번째 트리의 지름  (2) 2021.11.15
백준[16978] 수열과 쿼리 22  (0) 2021.11.13
백준[11375] 열혈강호  (0) 2021.11.13
복사했습니다!