题目意思: 一棵树,找到最少的点能覆盖到所有的边,(也就是每条边俩端 至少有一个在你找到的集合);
解法:每条边只能被俩个点中的一个,或全部覆盖所以我们有树形DP来解:
DP[num][flag]//代表在子树NUM全部被覆盖的情况下,flag=1,这个店也被覆盖:flag=false 这个店没被覆盖;
那么有了这样的想法大妈就很好写了毕竟树形DP 主要的初始化和合并的状态:
#include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <cstdlib> using namespace std; const int maxn=100003; int n; int dp[maxn][2]; struct Edge { int to,pre; Edge (int to=0,int pre=0):to(to),pre(pre){} }; Edge edge[maxn*2]; int head[maxn],pos; inline void add_edge(int s,int to) { edge[pos]=Edge(to,head[s]); head[s]=pos++; } inline void inint() { memset(head,-1,sizeof(head)); pos=0; } void dfs(int pa,int s) { dp[s][0]=0; dp[s][1]=1; for(int w=head[s];~w;w=edge[w].pre) { Edge &tmp=edge[w]; if(tmp.to==pa)continue; dfs(s,tmp.to); dp[s][0]+=dp[tmp.to][1]; dp[s][1]+=min(dp[tmp.to][0],dp[tmp.to][1]); } } int main() { int a,b; while(~scanf("%d",&n)) { inint(); memset(dp,0,sizeof(dp)); for(int i=2;i<=n;i++) { scanf("%d%d",&a,&b); add_edge(a,b); add_edge(b,a); } dfs(-1,1); printf("%d ",min(dp[1][0],dp[1][1])); } return 0; }