POJ 1192

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

题解:树形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 }

你可能感兴趣的:(poj)