[树形DP] poj 3659 Cell Phone Network
来源:互联网 发布:vs软件 编辑:程序博客网 时间:2024/05/17 22:54
最小支配集,求最小的点集覆盖所有的点。
/**[树形DP] poj 3659 Cell Phone Network给定一棵树,求最小支配集dp[i][0] = sum(min(dp[s][2],dp[s][1]))自己没被选,父节点被选中dp[i][1] = sum(min(dp[s][1],dp[s][2]))自己没被选,某儿子结点被选中dp[i][2] = sum(min(dp[s][0],dp[s][1],dp[s][2]))自己被选中求dp[i][1] 时需注意当所有的dp[s][1] < dp[s][2]时是不满足条件的。*/#include <stdio.h>#include <vector>#include <string.h>#include <algorithm>using namespace std;#define N 10001#define INF 100000000vector<int> g[N];int dp[N][3];void dfs(int u,int f){ dp[u][0] = 0; dp[u][1] = 0; dp[u][2] = 1; if(g[u].size() == 1 && g[u][0] == f) { dp[u][1] = INF; return ; } int i,flag = 0,minn = INF,dson = 0,v; for(i = 0; i < g[u].size(); ++i) { v = g[u][i]; if(v == f) continue; dfs(v,u); dp[u][2] += min(dp[v][0],min(dp[v][1],dp[v][2])); dp[u][0] += min(dp[v][2],dp[v][1]); if(dp[v][1] < dp[v][2]) { dp[u][1] += dp[v][1]; if(minn > dp[v][2]) { minn = dp[v][2]; dson = dp[v][1]; } } else { flag = 1; dp[u][1] += dp[v][2]; } } if(!flag) dp[u][1] += minn - dson;}int main(){ int n,a,b; scanf("%d",&n); --n; while(n--) { scanf("%d%d",&a,&b); g[a].push_back(b); g[b].push_back(a); } dfs(1,-1); printf("%d\n",min(dp[1][1],dp[1][2])); return 0;}