問題の意味
木を考えると、それは2未満の彼の点から消防署で覆うことができます。
どのように多くの消防署は、ツリー全体のニーズをカバーしようとしています。
分析
規制、ダイナミックレギュレーションを使用して、この問題の解決策を動かす貪欲考えやアイデアがあります。
したがって、木の従来のDPルーチンによれば、私たちは、標準としてサブツリー分割された状態を述べます。しかしながら、指摘することができるカバーすることができるサブツリーは、いくつかの点が明らかに存在してもよいです。
カバレッジ半径が2であるため、サブツリーの状態を5で割りました:
\(F_ {iが、0} \) 上向き2を覆います。
\(F_ {I、1} \) までカバーします。
\(F_ {I、2} \) だけ終了被覆サブツリー。
\(F_ {I、3} \) エンドカバー息子。
\(F_ {I、4} \) エンドカバー孫。
消防署の数が必要。
\(F_ {I、0} \) 自身を選択し、それが孫に上書きされます。すべての要件がカバーされているひ孫、息子0-4状態出会います。
\ [F_ {I、0} = 1 + \分(F_ {i.child、[0,4]})\]
\(F_ {I、1} \) 他の人の息子が被覆され、子ノードの1つから選択されます。しかし、他の息子の息子をカバーすることができません。転送、消防署がランダム請求息子の放電点と他の点を選択したときしたがって、被覆されています。
\ [F_ {iが、1} = \分(\分(F_ {i.child、[0,3]})_ {i.child!= K} + F_ {K、0})_ {k個の\で\ {i.childの\}} \]
同様にあり
\ [F_ {iが、2} = \分(\分(F_ {i.child、[0,2]})_ {i.child!= K} + F_ {K、1})_ {k個の\で\ {i.childの\}} \]
根の息子が覆われてみましょう、それは(良いZZああ)自体が覆われているようにすることです
\ [F_ {I、3} = \和(F_ {i.child、[0,2]})\]
同様にあり
\ [F_ {I、4} = \和(F_ {i.child、[0,3]})\]
早めます
最小値[0,2]をとり、つまり、ときにカバー自体への答え。
状態0、[0,4]と最も明らか4
\ [F_ {I、0} = 1 + \分(F_ {i.child、4})\]
同様にあり
\ [F_ {I、3} = \和(F_ {i.child、2})\]
\ [F_ {I、4} = \和(F_ {i.child、3})\]
ステータス0,3及び4が完了すると、それらは転送1及び2を最適化するために使用することができます。
状態1は、すべての孫を覆うことができ、次に取る\(F_ {i.child、0} {i.child、3} \ -f_) 最低。この式は、Iに隣接消防署カバレッジ所望の点の数に相当します。
だから、
\ [F_ {I、1} = \分(F_ {i.child、0} {-f_ i.child、3})+ F_ {I、4} \]
同様にあり
\ [F_ {I、2} = \分(F_ {i.child、2} -f_ {i.child、1})+ F_ {I、3} \]
最後に、あなたは役に立つか貪欲見つけることができます
(
コード
、醜い、またはコピーしないでください。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=1005;
int n,ne,head[MAXN],cnt,temp,temp1,temp2;
int f[MAXN][5];
bool tree[MAXN][MAXN];
int main()
{
scanf("%d",&n);
for(int i=2;i<=n;i++)
{
int x;
scanf("%d",&x);
tree[x][i]=1;
}
for(int i=n;i>=1;i--)
{
f[i][0]=1;
temp1=1919,temp2=1919;
for(int p=1;p<=n;p++)
{
if(tree[i][p])
{
f[i][3]+=f[p][2];
f[i][4]+=f[p][3];
f[i][0]+=f[p][4];
temp1=min(temp1,f[p][0]-f[p][3]);
temp2=min(temp2,f[p][1]-f[p][2]);
}
}
f[i][1]=f[i][4]+temp1;
f[i][2]=min(f[i][3]+temp2,min(f[i][0],f[i][1]));
f[i][3]=min(f[i][2],f[i][3]);
f[i][4]=min(f[i][4],f[i][3]);;
}
printf("%d",f[1][2]);
return 0;
}