POJ 1770 树形DP

题意:

容器中有 n 种原子,现提供 m 种光子,这 n 种原子中能量之差等于提供的 m 种光子之一所具有的能量,就认为这两种原子是处在容器在是危险的,现在要求取走一些原子,使得容器中的原子处在一块是安全的,同时要求剩下的原子的能量和最大。

 

思路:

很明显的树形dp,每两个处于会产生危险的原子连一条无向边,注意建图完了可能是一个森林!

PS:不会有环么?我AC了以后才发现这个问题。。。网上都没提这事,不知道我没完全理解题?

 

View Code
 1 #include <cstdio>

 2 #include <cstring>

 3 #include <cstdlib>

 4 #include <iostream>

 5 #include <cmath>

 6 #include <map>

 7 

 8 #define N 10000

 9 #define M 100000

10 

11 using namespace std;

12 

13 map<int,int> mp;

14 

15 int head[N],to[M],next[M],a[N],b[N],cnt,num,n,m,tc[N],dp[N][2];

16 bool vis[N];

17 

18 inline void add(int u,int v)

19 {

20     to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++;

21 }

22 

23 void read()

24 {

25     mp.clear();

26     memset(head,-1,sizeof head);cnt=0;

27     num=0;

28     for(int i=1;i<=n;i++) scanf("%d",&a[i]);

29     for(int i=1;i<=m;i++) scanf("%d",&b[i]);

30     for(int i=1;i<=n;i++)

31         for(int j=i+1;j<=n;j++)

32             for(int k=1;k<=m;k++)

33                 if(abs(a[i]-a[j])==b[k])

34                 {

35                     if(mp[a[i]]==0) {mp[a[i]]=++num;tc[num]=a[i];}

36                     if(mp[a[j]]==0) {mp[a[j]]=++num;tc[num]=a[j];}

37                     int ta=mp[a[i]],tb=mp[a[j]]; 

38                     add(ta,tb),add(tb,ta);

39                 }

40 }

41 

42 void find(int u,int fa)

43 {

44     vis[u]=true;

45     for(int i=head[u];~i;i=next[i])

46         if(to[i]!=fa) find(to[i],u);

47         

48     dp[u][1]=tc[u];dp[u][0]=0;

49     for(int i=head[u];~i;i=next[i])

50         if(fa!=to[i])

51         {

52             dp[u][0]+=max(dp[to[i]][1],dp[to[i]][0]);

53             dp[u][1]+=dp[to[i]][0];

54         }

55 }

56 

57 void go()

58 {

59     memset(dp,0x8f,sizeof dp);

60     memset(vis,0,sizeof vis);

61     int ans=0;

62     for(int i=1;i<=num;i++)

63         if(!vis[i])

64         {

65             find(i,-1);

66             ans+=max(dp[i][0],dp[i][1]);

67         }

68     printf("%d\n",ans);

69 }

70 

71 int main()

72 {

73     while(scanf("%d%d",&n,&m),n||m)

74     {

75         read();

76         go();

77     }

78     return 0;

79 }

 

 

 

你可能感兴趣的:(poj)