タイトル説明
ベッシーはすべて全国の牛が集まる毎年恒例の大牛を計画していると、当然のことながら、彼女は場所を取るために収集するための最も便利な場所を選択したいと思います。
ベッシーはこのラリーに参加するために将来的には全国から毎年恒例の集会牛、牛を計画しています。もちろん、彼女はこの集会を開催するための最も便利な場所を選ぶだろう。
各牛は、Nのいずれかに住んでいる(1 <= N <=10万)は、他に任意の納屋から取得することが可能であるような方法で、N-1の道路で接続されている異なる納屋(好都合番号1..N)道路を経由して納屋。道路iはa_iをとB_i(1 <= a_iを<= N、1 <= B_i <= N)納屋を接続し、長さL_iを(1 <= L_iを<= 1,000)を有しています。グレート牛の収集は、これらのNの納屋のいずれかに保持することができます。また、納屋私はそれに住んでC_I(0 <= C_I <=千)牛を有しています。
1ファーム内のN(1 <= N <=10万)に住んでいる各牛は、これらの農場は、道路N-1で接続されている、ファームからその他のファームに到達することができます。a_iをとB_iを接続するI農道(1 <= a_iを<= N、1 <= B_i <= N)、L_iをの長さ(1 <= L_iを<=千)。Nラリーは、農場でのいずれかの場所にあってもよいです。さらに、C_Iの各牛乗員(0 <= C_I <=千)牛。
牛の収集を保持するために納屋を選択する際、ベッシーは、選択された位置の(不便を最小化すると言うことである)利便性を最大化することを望みます。(I納屋のXへの納屋からの距離は、20その後、走行距離が* 20 C_Iがされている場合、すなわち)収集のための納屋Xを選ぶの不便は牛のすべてが納屋Xに到達するために移動する必要がある距離の合計であります。ベッシーは偉大な牛の収集のための最も便利な場所を選択するのに役立ち。
希望の程度を最大化するために、ベッシーは便利な集会の場所を選択するには(それが度を最小化するのは不便です)。例えば、会場などの第1のXファームを選択し、ファームI Xに到達するために、例えば、ファームから(ラリーの旅の和に出席するために牛の納屋で互いに度に不便であり、その後の総距離は、20でありますC_I * 20)。ベッシーは、大規模な集会を開催するための最も便利な場所を見つけるのに役立ちます。
様々な長さの様々な道路によって接続【様々な容量]を有する5つの納屋で国を考えます。納屋のこのセットでは、納屋3や納屋4軒の家屋任意の牛でもありません。
1 3 4 5
@ - 1 - @ - 3 - @ - 3 - @ [2]
[1] |
2 | @ [1] 2ベッシーは5つの納屋のいずれかにギャザリングを保持することができます。ここでは、各可能な場所について計算不便の表には、次のとおりです。
-----不便を収集------
場所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 0 0 6 15
5 7 8 0 0 0 15
ベッシーは納屋1の収集を保持している場合、各納屋から不都合があります。
納屋1 0 - そこには旅行時間!
納屋2 3 - 総走行距離は2 + 1 = 3×1牛です= 3納屋3 0 - そこには牛!
納屋4 0 - そこには牛!
バーン5 14 - 総走行距離は、したがって総不都合が17である3 + 3 + 1 = 7×2頭の牛= 14です。
可能な限り最高の利便性が納屋3、4、または5で収集を保持することによって、15、達成可能です。
入力形式
* 1行目:単一の整数:N
*行2..N + 1を:C_I:回線I + 1は、単一の整数が含まれています
*行N + 2..2 * N:a_iを、B_i、およびL_iを:私はN + 1 +ラインは三つの整数が含まれています
最初のライン:整数N.
第N + 1行目:最初の行は、I + 1の整数C_Iを有します
第2のn + 2行2 * Nへ:a_iを、B_i、およびL_iを:i線はN + 1つの整数行動3を+。
出力フォーマット
* 1行目:最小不便可能
最初のライン:最小値を表す値が便利ではありません。
サンプル入力と出力
5 1 1 0 0 2 1 3 1 2 3 2 3 4 3 4 5 3
15
説明/ヒント
ありがとう@ユーザー名は既に翻訳が存在します
あなたはラリーとして各点を列挙するために、場所を考慮した場合
DFSを使用して計算されます
そして、比較続きます
Oの時間複雑さ(N ^ 2)
しかし、nの範囲は明らかに残業、大きすぎます。
そこで、我々は、最適化する方法をすべきですか?
サンプルを見てみましょう
1 O(n)が計算されることで、出て取得することは簡単です
あなたが第1ノードを選択した場合、答えは17です
Oは、(N ^ 2)計算された時間内に解くことができないので
それはそれから再発することは可能ですか?
それは明らかに可能です。
あなたはすでに必要なノード番号1を観察する時間がわかっている場合
そこで、以下の仮定を行うことができます。
①すべての牛は、第1番ノードに到達します
3②長さとツリーノードの彼の子ノード1-> 3パスを返す必要があります
③彼のノード3とノードの長さに加えて、サブツリー進行を1-> 3パスを必要とします
上記の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; }