最小点覆盖
- 选择一个点,覆盖所有相邻边,最少选几个点能覆盖所有边
题意
- 给定一棵n个结点的树,选定一个结点后即可覆盖他的所有邻边,求覆盖所有邻边的最少选定结点数
思路
- 动态规划
- 对于每一个结点,由于覆盖边,所以自己考虑选和不选两种情况,且父亲没选,自己就一定得选,父亲选了,自己就可选可不选,注意区分最小点覆盖,最小边覆盖,最小支配集
代码
#include<bits/stdc++.h>
using namespace std;
/**
* dp[i][0/1];表示自己不选,自己选
* dp[i][1]=sum(min(dp[u][0],dp[u][1])+1;
* dp[i][0]=sum(dp[u][1]);
*/
vector <int> son[2000];
int dp[2000][2];
void dfs(int x,int fa){
dp[x][1]=1;
dp[x][0]=0;
for(auto i : son[x]){
if(i==fa) continue;
dfs(i,x);
dp[x][1]+=min(dp[i][0],dp[i][1]);
dp[x][0]+=dp[i][1];
}
}
int main(){
int n ;
while(scanf("%d",&n)!=EOF){
memset(dp,0,sizeof(dp));
for(int i=0;i<2000;i++){
son[i].clear();
}
int x,y,cnt ;
for(int j=0;j<n;j++){
scanf("%d:(%d)",&x,&cnt);
for(int i=0;i<cnt;i++){
scanf("%d",&y);
son[x].push_back(y);
son[y].push_back(x);
}
}
dfs(0,-1);
cout << min(dp[0][0],dp[0][1]) << endl;
}
return 0;
}