POJ 2342 树的最大独立集
题意:在树的最大独立集的基础上,加上权值。求最大。
分析:
采用刷表的方式写记忆化,考虑一个点选和不选,返回方式pair 型。
首先,无根树转有根树,dp(root)。
注意的是:u不选,那么他的子节点,可以选,或者不选。WA了无数次。
#include <cstdio> #include <vector> #include <cmath> using namespace std; const int maxn = 6000+5; vector<int> G[maxn]; int a[maxn]; int p[maxn]; void dfs(int u,int fa) { int d = G[u].size(); for(int i=0; i<d; i++) { int v = G[u][i]; if(v!=fa) dfs(v,p[v]=u); } } int d[maxn][2]; bool vis[maxn]; void dp(int u) { if(vis[u]) return; vis[u] = 1; for(int i=0; i<G[u].size(); i++) { int v = G[u][i]; if(v!=p[u]) { dp(v); d[u][1] +=d[v][0]; d[u][0] +=max(d[v][1],d[v][0]); } } } int main() { //freopen("in.txt","r",stdin); int n; scanf("%d",&n); for(int i=1; i<=n; i++) { scanf("%d",&a[i]); d[i][1] = a[i]; } int u,v; while(scanf("%d%d",&u,&v),u+v) { G[u].push_back(v); G[v].push_back(u); } p[1] = -1; dfs(1,-1); dp(1); printf("%d\n",max(d[1][0],d[1][1])); return 0; }