# (트리 DP) 루오 구 P2986은 [USACO10MAR] 큰 소가 멋진 암소를 수집 갓 (증가 + / 지방 선거 -)

제목 설명

베시는 물론, 그녀가 수집이 수행하기위한 가장 편리한 위치를 선택하고자하는 모든 전국의 소에 대한 수집 연간 멋진 암소를 계획하고있다.

베시는 연간 집회 소를 계획하고, 향후 전국에서 소는이 집회에 참여합니다. 물론, 그녀는이 모임을 개최하는 가장 편리한 위치를 선택합니다.

각 소 N 중 하나에 산다 (1 <= N <= 10)은 다른 어떤 축사에서 얻을 수있는 방식으로 N-1 길로 연결된 다른 질러 (편리 번호 1..N) 도로를 통해 헛간. 도로 나 A_I 및 B_i (1 <= A_I <= N 1 <= B_i <= N) 질러 연결 길이 L_i (1 <= L_i <= 1000)을 갖는다. 위대한 암소 수집 이러한 N 축사 중 하나에서 개최 할 수있다. 또한, 헛간 내가 살고 C_I (0 <= C_I <= 1000) 소있다.

N 거주 각 소 (1 <= N <= 10)가 하나 개 팜, 팜이도는 N-1로 연결되며, 농장에서 다른 농장에 도달 할 수있다. A_I 및 B_i 연결 I 농로 (1 <= A_I <= N 1 <= B_i <= N) L_i의 길이 (1 <= L_i <= 1000). N 집회는 농장에있는 한 곳에서 할 수있다. 또한, 각각의 암소 C_I 탑승자 (0 <= C_I <= 1000) 소.

암소의 모임을 개최 할 수있는 헛간을 선택할 때, 베시가 선택한 위치 (불편을 최소화 말을하는 것입니다) 편의를 극대화하고자. (I 축사 X에 반까지의 거리가 20 그 이동 거리가 20 * C_I이되는 경우, 즉,)를 수집 축사 X를 선택해야하는 불편 함이 소 모든 축사 X 도달하도록 이동하는데 필요한 거리의 합 . 베시는 큰 암소 수집을위한 가장 편리한 위치를 선택 도와주세요.

집회의 위치를 ​​선택하는 경우, 편리한 베시 (즉 정도를 최소화하는 불편) 희망의 정도를 극대화 할 수 있습니다. 예를 들어, 장소 등 최초의 X 농장을 선택, 농장 나는 X에 도달하기 위해, 예를 들어, 농장에서 (집회의 여행 합에 참석하기 위해 암소 헛간에서 서로의 정도에 불편 후 총 거리이며, 20 C_I * 20). 베시는 대규모 집회를 개최하는 가장 편리한 위치를 찾을 수 있습니다.

다양한 길이의 여러 길로 연결 [다양한 용량] 다섯 헛간과 국가를 생각 해보자. 축사의 세트, 어느 헛간 3이나 헛간 4 하우스 모든 소에.

1 2 3 4 5

@ - 1 - @ - 3 - @ - 3 - @ [2]

[1] |

2 | @ [1] 2 베시 다섯 개 질러 임의의 수집을 수납 할 수있는; 여기에서 각각의 가능한 위치에 대하여 계산 불편 테이블이다 :

----- 불편을 수집 ------

위치 B1 B2의 B3 B4의 B5의 총

1 0 3 0 0 14 17

2 3 0 0 0 16 19

3 1 2 0 0 12 15

4 4 5 0 0 6 15

7 8 5 0 0 0 15

베시 반 (1)의 집합을 유지하는 경우, 각각의 반에서 불편하다 :

반 1 0 - 거기의 여행 시간!

반 2 3 - 총 이동 거리가 2 + 1 = 3 × 1 = 3 반 암소 3 - 0이 아니 소!

반 4 0 - 거기의 소!

반 5 14 - 총 이동 거리가 14 그래서 총 불편 17 3 + 1 = 3 + 7 × 2 개 = 소이다.

최상의 편의 질러 3, 4 또는 5의 수집을 유지시킴으로써 15, 달성 가능하다.

입력 형식

* 행 1 : 단일 정수 : N

* 라인 2..N + 1 : 선 내가 1은 하나의 정수가 포함 + : C_I를

* 라인 N + N * 2..2 : A_I, B_i 및 L_i : N + 1은 세 정수를 포함 광고 나 +

첫번째 라인 : 정수 N.

제 N + 1 라인 : 제 라인 I + 1의 정수를 갖는다 C_I

N + 2 번째 행은 2 * N : 광고 나 N + 1의 정수 거동 3 + : A_I, B_i 및 L_i한다.

출력 형식

첫 줄 수있는 최소 불편

첫 번째 줄 : 최소 값을 나타내는 값이 편리하지 않습니다.

샘플 입출력

입력 # 1
5 
1 
1 
0 
0 
2 
1 3 1 
2 3 2 
3 4 3 
4 5 3
출력 # 1
(15) 

설명 / 팁

감사합니다 @ 사용자 이름은 이미 번역이 존재

당신은 집회로 각 지점을 열거하기 위해 위치를 고려하는 경우

DFS를 사용하여 계산된다

그런 다음 비교 다음

O의 시간 복잡도 (N ^ 2)

그러나 N의 범위가 너무 큽니다 분명히 초과입니다.

최적화하는 방법을 그래서 우리는해야 하는가?

샘플에서보세요

여기에 설명 된 사진을 쓰기

하나의 O (n)을 계산함으로써, 나가 쉽게

당신이 제 1 노드를 선택하면, 대답은 17

때문에 O (N ^ 2) 계산 된 시간 내에 해결 될 수 없다

그것은 그것의 재발 할 수 있습니까?

그것은 분명히 가능하다.

이미 시간을 알고있는 경우에 필요한 노드 번호 하나를 관찰

그래서 우리는 다음과 같은 가정을 만들 수 있습니다 :

① 모든 소 먼저 제 1 노드에 도달

3 ② 길이와 트리 노드의 자신의 자식 노드는 1> 3 경로를 반환해야

③ 그 노드 3 및 노드의 길이 외에 서브 트리를 진행 1-> 3 패스를 필요

위의 세 가지를 통해, 우리는 아이가 부모로부터 노드 언제든지 시작할 수 있습니다

그래서, 다시 최종 답변을 시작하는 데에 O (N)를 계산한다

#include<iostream>
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> using namespace std; #define MAX 200100 #define ll long long inline ll read() { register ll x=0,t=1; register char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-'){t=-1;ch=getchar();} while(ch<='9'&&ch>='0'){x=x*10+ch-48;ch=getchar();} return x*t; } ll dis[MAX],C[MAX],Q[MAX],f[MAX],Sum,Ans=1000000000000000000; struct Line { ll v,next,w; }e[MAX]; ll h[MAX],cnt=1,N; inline void Add(ll u,ll v,ll w) { e[cnt]=(Line){v,h[u],w}; h[u]=cnt++; } //使用两遍DFS //第一遍以任意点为根节点计算一遍 //dis[i]表示以i为根的子树到根的距离之和 ll DFS(ll u,ll ff) { ll tot=0; for(ll i=h[u];i;i=e[i].next) { ll v=e[i].v; if(v!=ff) { ll s=DFS(v,u);//子树上牛的数量 dis[u]+=dis[v]+e[i].w*s;//统计 tot+=s;//牛的个数 } } return Q[u]=tot+C[u]; } //第二遍计算偏移后的值 //先可以假设走到当前节点的父节点 //再让当前自己点所有牛退回来,父节点的所有牛走过去即可 void DFS2(ll u,ll ff) { for(ll i=h[u];i;i=e[i].next) { ll v=e[i].v; if(v!=ff) { ll ss=e[i].w; f[v]=f[u]-Q[v]*ss+(Sum-Q[v])*ss; DFS2(v,u); } } } int main() { N=read(); for(ll i=1;i<=N;++i) C[i]=read(); for(ll i=1;i<=N;++i) Sum+=C[i];//统计牛的总数 for(ll i=1;i<N;++i) { ll u=read(),v=read(),w=read(); Add(u,v,w); Add(v,u,w); } DFS(1,1);//求出以1为聚集处的结果 DFS2(1,1);//求出其他的偏移值 for(ll i=1;i<=N;++i) Ans=min(Ans,f[i]); cout<<Ans+dis[1]<<endl; return 0; }

추천

출처www.cnblogs.com/little-cute-hjr/p/11440790.html