树上的最小点覆盖,如果不是树则是NP复杂问题。
对于树上的某个点,如果不被选中,则它相邻的节点必然被选中,如果选中它,则取相邻节点选中或不选中的较小值。
代码很简单。
#include<cstdio> #include<cstdlib> #include<cmath> #include<vector> using namespace std; const int maxn=1500; vector<int> adj[maxn]; int dp[maxn][2]; int dfs(int cur,int flag,int fa) { if(dp[cur][flag]!=-1)return dp[cur][flag]; if((adj[cur].size()==0&&fa==-1)||(adj[cur].size()==1&&adj[cur][0]==fa)) return flag; int ans=flag; for(int i=0;i<adj[cur].size();i++) { int ne=adj[cur][i]; if(ne==fa)continue; if(flag==0)ans+=dfs(ne,1-flag,cur); else ans+=min(dfs(ne,flag,cur),dfs(ne,1-flag,cur)); } return dp[cur][flag]=ans; } int main() {freopen("t.txt","r",stdin); int n; while(scanf("%d",&n)!=EOF) {for(int i=0;i<n;i++)dp[i][0]=dp[i][1]=-1; for(int i=0;i<n;i++)adj[i].clear(); for(int i=0;i<n;i++) { int np;scanf("%d",&np);getchar();getchar(); int m,ne;scanf("%d",&m);getchar(); for(int j=0;j<m;j++) { scanf("%d",&ne); adj[np].push_back(ne); adj[ne].push_back(np); } } printf("%d\n",min(dfs(0,0,-1),dfs(0,1,-1))); } return 0; }