题目链接:https://vjudge.net/problem/UVALive-2038
题意:给定一棵树,选择尽量少的点,
使得每个没有选中的结点至少和一个已经选中的结点相邻。
输出最少需要选择的节点数。
思路:经典的二分图最小顶点覆盖, 也是经典的树形 DP
AC代码:
#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXN=1500+10;
int d[MAXN][2],n;
vector<int>G[MAXN];
int f(int u,int fa,int mark)
{
if(d[u][mark]!=-1) return d[u][mark]; //记忆化
int &ans=d[u][mark];
ans=mark;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(v==fa) continue;
if(mark) ans+=min(f(v,u,0),f(v,u,1)); //选
else ans+=f(v,u,1);//不选
}
return ans;
}
int main()
{
while(~scanf("%d",&n))
{
int u,v,t;
for(int i=0;i<=MAXN;i++) G[i].clear();
for(int i=0;i<n;i++)
{
scanf("%d:(%d)",&u,&t);
for(int j=0;j<t;j++)
{
scanf("%d",&v);
G[u].push_back(v);
G[v].push_back(u);
}
}
memset(d,-1,sizeof(d));
int sum=min(f(0,-1,0),f(0,-1,1));
printf("%d\n",sum);
}
}