经典问题系列
覆盖半径(1)的最小点覆盖集
(f[i][0]) 表示不在此处建信号塔,但(i)及其子树都有信号
(f[i][1]) 表示在此处建信号塔,但(i)及其子树都有信号
(f[i][2]) 表示不在在此处建信号塔,但(i)子树都有信号,而(i)无信号
(f[p][2]=sum f[q][0])
(f[p][1]=sum min(f[q][0],f[q][1],f[q][2]))
(f[p][0]=min_q (f[q][1]+sum_k min(f[k][0],f[k][1])))
答案就是 (min(f[1][0],f[1][1]))
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1000005;
vector <int> g[N];
int vis[N],f[N][3],t1,t2,t3,n;
void dfs(int p) {
vis[p]=1;
int fa=0;
f[p][1]=1;
for(int i=0;i<g[p].size();i++) {
int q=g[p][i];
if(vis[q]==0) {
dfs(q);
f[p][2]+=f[q][0];
f[p][1]+=min(f[q][0],min(f[q][1],f[q][2]));
}
else fa=q;
}
f[p][0]=1e+16;
for(int i=0;i<g[p].size();i++) {
int q=g[p][i];
if(q!=fa) {
int tmp=f[q][1];
for(int j=0;j<g[p].size();j++) {
int k=g[p][j];
if(k!=fa && k!=q) {
tmp += min(f[k][0],f[k][1]);
}
}
f[p][0]=min(f[p][0],tmp);
}
}
}
signed main() {
scanf("%lld",&n);
for(int i=1;i<n;i++) {
scanf("%lld%lld",&t1,&t2);
g[t1].push_back(t2);
g[t2].push_back(t1);
}
dfs(1);
cout<<min(f[1][0],f[1][1])<<endl;
}