题意:题目叙述很长,但很简单,其实如果是英文题倒还可以狠狠的恶心一下人的= =!就是给一个无向树,求最大权子树

题解:树形dp,dp[i][0]代表不要第i个点时以i为根的子树的最大价值,dp[i][1]代表必须要i时以i为根的子树的最大值。于是dp[i][0]=max(dp[i][0],dp[j][0],dp[j][1]),j为i能到的点,dp[i][1]=val+sum(max(dp[j][1],0)),即取所有权值为正的i的子树与它相连,注意必须是dp[i][1],因为要保证树最后的连通性。

View Code
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=1005;
 6 int head[N],nc;
 7 struct Edge
 8 {
 9     int to,next;
10 }edge[N*5];
11 int val[N],dp[N][2];
12 bool vis[N];
13 void add(int a,int b)
14 {
15     edge[nc].to=b;edge[nc].next=head[a];head[a]=nc++;
16     edge[nc].to=a;edge[nc].next=head[b];head[b]=nc++;
17 }
18 void dfs(int now)
19 {
20     dp[now][1]=val[now];
21     dp[now][0]=0;
22     vis[now]=true;
23     for(int i=head[now];i!=-1;i=edge[i].next)
24     {
25         int to=edge[i].to;
26         if(!vis[to])
27         {
28             dfs(to);
29             dp[now][1]+=max(dp[to][1],0);
30             dp[now][0]=max(dp[now][0],max(dp[to][1],dp[to][0]));
31         }
32     }
33 }
34 int po[N][2];
35 int main()
36 {
37     int n;
38     while(scanf("%d",&n)!=EOF)
39     {
40         memset(head,-1,sizeof(head));
41         memset(vis,false,sizeof(vis));
42         nc=0;
43         for(int i=0;i<n;i++)
44         {
45             scanf("%d%d%d",&po[i][0],&po[i][1],&val[i]);
46             for(int j=0;j<i;j++)
47             {
48                 if(abs(po[i][0]-po[j][0])+abs(po[i][1]-po[j][1])==1)
49                     add(i,j);
50             }
51         }
52         dfs(0);
53         printf("%d\n",max(dp[0][0],dp[0][1]));
54     }
55     return 0;
56 }