AcWing 1077. 황궁 간수 (나무형 DP) 문제 풀이
제목 설명
태평 왕세자 사건 이후 육 소 봉 은 황제 가 특별히 초빙 한 어전 품 시위 가 되 었 다.
황궁 은 오문 을 기점 으로 후궁 빈궁 들 의 침실 까지 나무 모양 으로 어떤 궁전 들 은 서로 볼 수 있다.
대내 보위 가 삼엄 하고 세 걸음 한 걸음, 다섯 걸음 한 걸음 보초 가 있 으 며 모든 궁전 은 전 천후 에 지 키 는 사람 이 있어 야 하 며 서로 다른 궁전 에서 지 키 는 데 필요 한 비용 이 다르다.
그러나 육 소 봉 은 경비 가 부족 해서 어떻게 든 궁전 마다 시 위 를 지 킬 수 없 었 다.
육 소 봉 이 시 위 를 배치 하 는 것 을 도와 모든 궁전 을 지 키 는 전제 에서 비용 이 가장 적 게 든다.
입력 형식
입력 중 데이터 설명 트 리 는 다음 과 같 습 니 다.
첫 번 째 줄 n 은 나무의 결점 수 를 나타 낸다.
두 번 째 줄 에서 n + 1 줄 까지 모든 궁전 의 노드 정 보 를 묘사 합 니 다. 그 다음 에 이 궁전 의 노드 레이 블 i, 이 궁전 에 시위 에 필요 한 경비 kk, 이 노드 의 자 결 점 수 m, 그 다음 m 개 수 는 각각 이 노드 의 mm 키 노드 의 레이 블 r1, r2, rm 입 니 다.
n 개의 노드 트 리 에 대해 노드 레이 블 은 1 에서 n 사이 이 고 레이 블 은 중복 되 지 않 습 니 다.
출력 형식
하나의 정 수 를 출력 하여 가장 적은 경 비 를 표시 하 다.
데이터 범위
1≤n≤1500
입력 예시:
6 1 30 3 2 3 4 2 16 2 5 6 3 5 0 4 4 0 5 11 0 6 5 0
출력 예시:
25
샘플 설명:
2, 3, 4 결점 에 호 위 를 배치 하면 궁전 전 체 를 관찰 할 수 있 으 며 필요 한 경비 가 16 + 5 + 4 = 25 로 가장 적다.
문제 풀이:
트 리 DP:
f [N] [3] 은 3 가지 상 태 를 나타 낸다. 0 은 아버지 노드 가 수 비 를 놓 았 다 는 뜻 이 고 1 은 아들 노드 가 수 비 를 놓 았 다 는 뜻 이 며 2 는 자신 이 수 비 를 놓 았 다 는 뜻 이다.
f [u] [0] + = min (f [j] [i], f [j] [2]) 부모 노드 가 수 비 를 놓 으 면 바이트 점 을 놓 을 수 있 고 놓 지 않 을 수 있 습 니 다. 우 리 는 최소 값 을 가 집 니 다.
f [u] [2] + = min (f [j] [0], min (f [j] [1], f [j] [2]) 자신 이 수 비 를 놓 았 습 니 다. 하위 노드 는 놓 아 도 되 고 놓 지 않 아 도 되 며 3 가지 상태의 최소 치 를 제거 합 니 다.
사고 서브 노드 가 수 비 를 놓 은 상황:
어느 하위 노드 가 수 비 를 놓 았 는 지, 즉 f [j] [2] 를 열거 합 니 다. 다른 하위 노드 는 놓 을 수 있 고 놓 지 않 을 수 있 습 니 다. 먼저 sum 으로 하위 노드 값 의 총 계 를 구 할 수 있 습 니 다. 즉, f [u] [0] 입 니 다.
f [u] [0] - min (f [j] [1], - f [j] [2]) 은 j 라 는 하위 노드 의 다른 하위 노드 의 총 계 를 제거 하 는 것 을 나타 낸다.
출시: f [u] [1] = min (f [u] [1], f [j] [2] + f [u] [0] - min (f [j] [1], f [j] [2]);
#include
#include
using namespace std;
const int N = 1510;
int h[N], e[N], w[N], ne[N], idx;
int f[N][3]; //3 0 ,1 ,2
int n, m, a, b, c;
int vis[N];
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
void dfs(int u)
{
f[u][2] = w[u];
int sum = 0; // f[j][1], f[j][2]
for(int i = h[u]; i != -1; i = ne[i]){
int j = e[i];
dfs(j);
f[u][0] += min(f[j][1], f[j][2]);
f[u][2] += min(f[j][0], min(f[j][1], f[j][2]));
}
f[u][1] = 1e9;
for(int i = h[u]; i != -1; i = ne[i]){
int j = e[i];
// j
//f[u][0] - min(f[j][1], - f[j][2]) j ;
f[u][1] = min(f[u][1], f[j][2] + f[u][0] - min(f[j][1], f[j][2]));
}
}
int main()
{
cin >> n;
memset(h, -1, sizeof h);
memset(vis, false, sizeof vis);
for(int i = 1; i <= n; i++){
cin >> a >> c >> m;
w[a] = c;
while(m--){
cin >> b;
add(a, b);
vis[b] = true;
}
}
int root = 1;
while(vis[root])root++; //
dfs(root);
cout << min(f[root][1], f[root][2]) << endl;
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
124. 두 갈래 나무의 최대 경로와 leetcode비공 두 갈래 트리를 지정하고 최대 경로와 를 되돌려줍니다. 본고에서 경로는 나무의 임의의 노드에서 출발하여 임의의 노드에 도달하는 서열로 정의되었다.이 경로는 루트 노드를 거치지 않고 하나 이상의 노드를 포함합니다...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.