POJ1192 最优连通子集(树形DP)
单整点集V是无向无环图,可以看作树。
dp[u]表示,选取u点时u点和它子树最大的权和。
而某个点不选,那么它和它子树的最大权和是0,因为题目求的集合要连通。
状态转移方程是:dp[u]=∑max(0,dp[son(u)])。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define MAXM 2222 7 #define MAXN 1111 8 #define INF (1<<29) 9 10 struct Edge{ 11 int v,next; 12 }edge[MAXM]; 13 int head[MAXN],NE; 14 void addEdge(int u,int v){ 15 edge[NE].v=v; edge[NE].next=head[u]; 16 head[u]=NE++; 17 } 18 19 int n,x[MAXN],y[MAXN],w[MAXN]; 20 int d[MAXN]; 21 bool vis[MAXN]; 22 int dfs(int u){ 23 if(d[u]!=-INF) return d[u]; 24 int res=w[u]; 25 for(int i=head[u]; i!=-1; i=edge[i].next){ 26 int v=edge[i].v; 27 if(vis[v]) continue; 28 vis[v]=1; 29 res+=max(0,dfs(v)); 30 } 31 return d[u]=res; 32 } 33 int main(){ 34 while(~scanf("%d",&n)){ 35 for(int i=0; i<n; ++i){ 36 scanf("%d%d%d",x+i,y+i,w+i); 37 } 38 memset(head,-1,sizeof(head)); 39 for(int i=0; i<n; ++i){ 40 for(int j=i+1; j<n; ++j){ 41 if(abs(x[i]-x[j])+abs(y[i]-y[j])==1){ 42 addEdge(i,j); 43 addEdge(j,i); 44 } 45 } 46 } 47 for(int i=0; i<n; ++i){ 48 d[i]=-INF; 49 vis[i]=0; 50 } 51 vis[0]=1; 52 dfs(0); 53 int res=0; 54 for(int i=0; i<n; ++i){ 55 res=max(res,d[i]); 56 } 57 printf("%d\n",res); 58 } 59 return 0; 60 }