题目意思: 一棵树,找到最少的点能覆盖到所有的边,(也就是每条边俩端 至少有一个在你找到的集合);
解法:每条边只能被俩个点中的一个,或全部覆盖所以我们有树形DP来解:
DP[num][flag]//代表在子树NUM全部被覆盖的情况下,flag=1,这个店也被覆盖:flag=false 这个店没被覆盖;
那么有了这样的想法大妈就很好写了毕竟树形DP 主要的初始化和合并的状态:
#include#include #include #include #include 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\n",min(dp[1][0],dp[1][1])); } return 0;}