木の直径について話します
定義:
ノードノードツリー最大サブツリーの最小数。
自然:
1.元のツリーの1/2、重心までの2つとツリーを超えていないすべてのサブツリー・ノードの重力の結果として生じる中心を削除します。
すべてのノードと重心の最小距離、重心が2つであり、それらは等距離2.ツリーである場合に、
3.合併、2つの元のツリーパスの重心における重力の新しい中心による木の両側。
4.ツリーがリーフノードを削除したり追加し、重心の片側のみが上方に移動します。
解決:
多様を解決するための方法は、異なる定義および特性を使用しました:
解決1.定義:
SIZ [i]が表すノードI DP [i]は、iのサブツリーの大きさは、iノードstraightaway右点についてヴァル[i]は、最大ルートのサブツリーの大きさで表されているが、コードを説明します
インラインボイド DFSは(int型今、INT FA)
{
SIZ [今] = valの[今]。
DP [今] = 0 ;
以下のために(int型 ; I I = I =ヘッド[今] [I] .nxt)
{
int型 T = A [i]の.TO。
場合(T FAを==)続けます。
DFS(今トン、);
SIZ [今] + = SIZ [T]。
DP [今] = MAX(DP [今]、SIZ [T])。
}
DP [今] = MAX(DP [今]、N- DP [今])。
もし(DP [今] <DP [ANS])ANS =今;
}
2.自然の解決:
一般的には十分な解決定義されていますが、時々、より便利で実用的な性質を解決。
2の性質:我々はノードへのすべてのノードを処理することができる距離は、最小値をとります。
どのように行うには、各ノードのノードから得ましたか?それは非常に簡単ですので、我々は最初の距離を扱うことができ、処理中に、DFSダウンでqwqルートにすべてのノード。
。。SIZ [I]同上、F [i]はiはノードのすべての子ノードを表し、iは距離であり、ヴァル[I]同上は、[i]の右側に.val、1は、ルートノードとして設定されています。
インラインボイド DFS1(int型、今INTの FAを、INT 深い)
{
SIZ [今] = valの[今]。
[今] DEP = 深いです。
以下のために(int型 ; I I = I =ヘッド[今] [I] .nxt)
{
int型 T = A [i]の.TO。
場合(T FAを==)続けます。
DFS1(T、今、深い + [I] .val)。
SIZ [今] + = SIZ [T]。
F [今] + = F [T] + SIZ [T] * [I] .val。
}
}
プロセスのためにFは、その配列を認識:すべての子は今+距離を距離の現在のサブツリーのすべてのノードをtにTノード。
これは、ルートから入手し、ルートノードの我々次いで再帰他のノードの距離を通って、宣伝以下の通りです。
f [ now ] = f [ fa ] +( siz [ 根节点 ] - 2 * siz [ now ])* 边权;(now!= 根节点)
理解如下:
对于now的子节点,每个节点的距离减少了一个边权,总距离减少 siz [ now ] * 边权 ,对于非v子节点,每个节点距离增加了一个边权,总距离增加(siz[ 根 ]-siz [ now ])*边权
inline void dfs2(int now,int fa)
{
if(now^root) f[now]=f[fa]+siz[1]-2*siz[now];
if(f[now]<sum) res=now,sum=f[now];
for(int i=head[now];i;i=a[i].nxt)
{
int t=a[i].to;
if(t==fa) continue;
dfs2(t,now);
}
}
to be continue……