树形DP。
思路参考题解。
典型的树形
不妨设为x节点被自己影响,为被儿子影响,为被父亲影响
显然,
而,即被自己的儿子影响,只要x所有的儿子中有一个放了信号塔就ok了,其余的儿子放不放无所谓
那么我们可以枚举这个儿子是谁
假设这个儿子是,除以外的儿子是
那么最终$f[x][1]=f[sn][0]+min(f[u][1],f[u][0]) $$//uf[x][2]$
看题解吧写的好多了
细节见代码.
#include <bits/stdc++.h>
#define ll long long
#define maxn 10001
using namespace std;
ll n,u,v,hd[maxn],ct,fa[maxn],f[maxn][3];
struct Node{
ll to,nx;
}e[maxn<<2];
inline ll read(){
ll x=0,f=0;
char c=getchar();
while(!isdigit(c))
f|=c=='-',c=getchar();
while(isdigit(c))
x=(x<<1)+(x<<3)+(c^48),c=getchar();
return f?-x:x;
}
inline void add(ll x,ll y){
e[++ct].to=y;
e[ct].nx=hd[x];
hd[x]=ct;
}
inline void dfs(ll x){
ll sn=0;
f[x][0]=1;
for(register int i=hd[x];i;i=e[i].nx){
ll u=e[i].to;
if(u!=fa[x]){
fa[u]=x;
dfs(u);
f[x][0]+=min(f[u][0],min(f[u][1],f[u][2]));
f[x][2]+=min(f[u][0],f[u][1]);
if((f[sn][0]-min(f[sn][0],f[sn][1]))>(f[u][0]-min(f[u][0],f[u][1])))
sn=u;
}
}
f[x][1]=f[sn][0];
for(register int i=hd[x];i;i=e[i].nx){
ll u=e[i].to;
if(fa[x]==u||sn==u) continue;
f[x][1]+=min(f[u][0],f[u][1]);
}
}
int main(){
n=read();
for(register int i=1;i<n;++i){
u=read();v=read();
add(u,v);add(v,u);
}
f[0][0]=0x3f3f3f3f;
dfs(1);
printf("%lld\n",min(f[1][0],f[1][1]));
return 0;
}