题目大意:
给你一棵树 选一个点既选择了与其相邻的边,求选择最少的点包含全部的边;
思路:入门题:对于每一个节点,选与不选2个状态,如果不选,那么他的子节点必须都要选
dp[u][0] 不选u
dp[u][1] 选u;
#include<cstdio> #include<cstring> #include<vector> #include<iostream> using namespace std; const int maxn=1e5+10; #define mem(a,b) memset(a,b,sizeof(a)) vector<int>q[maxn]; int dp[maxn][3]; void init(int n) { for(int i=0;i<n;i++) q[i].clear(); mem(dp,0); } void creat_edge(int u,int v) { q[u].push_back(v); } void dfs(int u,int fa) { int t=q[u].size(); for(int i=0;i<t;i++) { int v=q[u][i]; if(v==fa) continue; dfs(v,u); dp[u][0]+=dp[v][1]; dp[u][1]+=min(dp[v][0],dp[v][1]); } dp[u][1]+=1; } int main() { int n; while(~scanf("%d",&n)) { init(n); int u,mub; for(int i=1;i<=n;i++) { scanf("%d",&u); scanf(":(%d)",&mub); //cin>>u; //cout<<u<<" "; //cin>>ch>>ch>>mub>>ch; //cout<<mub<<endl; for(int i=1;i<=mub;i++) { int v; scanf("%d",&v); creat_edge(u,v); creat_edge(v,u); } } dfs(0,-1); printf("%d ",min(dp[0][0],dp[0][1])); //cout<<min(dp[0][0],dp[0][1])<<endl; } return 0; }