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 }

 

posted @ 2016-01-01 21:31  WABoss  阅读(247)  评论(0编辑  收藏  举报