题意:题目叙述很长,但很简单,其实如果是英文题倒还可以狠狠的恶心一下人的= =!就是给一个无向树,求最大权子树
题解:树形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 }