• 【UVALive4685-Succession】树形DP


    http://acm.hust.edu.cn/vjudge/problem/14338

    题意:给定一棵树,每个点有一个值,让你选择k个点,并且这k个点是连在一起的(从任意一个点出发,可以遍历完所有选择的点 并且 不经过没有被选择的点),让这k个点的价值总和最大,纹方案数(Mod1000000007)。

    题解:设d[x][k]为必须选择x,以x为根的子树中共选择了k个节点,价值总和最大是多少。

           f[x][k]为d[x][k]对应的方案数是多少。

    对于x,我们把x的孩子son不断地并到f[x]中。

    对于每一个son:d[x][j]=maxx(d[x][j-k],d[son][k]);

    需要注意的就是上式中d[x][j]不断地变化,对于当前的son,j变大的时候可能用到的d[x][j-k]是用当前的son更新的。所以要开一个p[x][j]等于当前的son没更新x的时候d[x][j]的值,同理q[x][j]=f[x][j]。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 using namespace std;
      7 
      8 typedef long long LL;
      9 const int N=110;
     10 const LL Inf=(LL)1e9,Mod=1000000007;
     11 struct node{
     12     int x,y,next;
     13 }a[2*N];
     14 int len,n,m,r;
     15 int first[N],son[N],w[N];
     16 LL a1,a2,d[N][N],f[N][N],p[N][N],q[N][N];
     17 
     18 void ins(int x,int y)
     19 {
     20     len++;
     21     a[len].x=x;a[len].y=y;
     22     a[len].next=first[x];first[x]=len;
     23 }
     24 
     25 void dfs(int x,int fa)
     26 {
     27     son[x]=1;
     28     for(int i=first[x];i;i=a[i].next)
     29     {
     30         int y=a[i].y;
     31         if(y==fa) continue;
     32         dfs(y,x);
     33         son[x]+=son[y];
     34     }
     35 }
     36 
     37 void copy(int x)
     38 {
     39     for(int i=0;i<=n;i++) p[x][i]=d[x][i],q[x][i]=f[x][i];
     40 }
     41 
     42 void dp(int x,int fa)
     43 {
     44     for(int i=1;i<=n;i++) d[x][i]=-Inf;
     45     memset(f[x],0,sizeof(f[x]));
     46     d[x][0]=0;f[x][0]=1;d[x][1]=w[x];f[x][1]=1;
     47     
     48     copy(x);
     49     
     50     for(int i=first[x];i;i=a[i].next)
     51     {
     52         int y=a[i].y;
     53         if(y==fa) continue;
     54         dp(y,x);
     55         for(int j=2;j<=son[x];j++)
     56         {
     57             for(int k=1;k<=son[y] && (j-k)>=1;k++)
     58             {
     59                 LL dd=p[x][j-k]+d[y][k];
     60                 LL ff=(q[x][j-k]*f[y][k])%Mod;
     61                 if(dd > p[x][j]) 
     62                 {
     63                     if(dd>d[x][j]) d[x][j]=dd,f[x][j]=ff;
     64                     else if(dd==d[x][j]) f[x][j]=(f[x][j]+ff)%Mod;
     65                 }
     66                 else if(dd == p[x][j])
     67                 {
     68                     if(dd==d[x][j]) f[x][j]=(f[x][j]+ff)%Mod;
     69                 }
     70             }
     71         }
     72         copy(x);
     73     }
     74     
     75     if(d[x][m]>a1) a1=d[x][m],a2=f[x][m];
     76     else if(d[x][m]==a1) a2=(a2+f[x][m])%Mod;
     77 }
     78 
     79 int main()
     80 {
     81     freopen("a.in","r",stdin);
     82     // freopen("a.out","w",stdout);    
     83     int T;
     84     scanf("%d",&T);
     85     while(T--)
     86     {
     87         len=0;
     88         memset(first,0,sizeof(first));
     89         scanf("%d%d%d",&n,&m,&r);
     90         for(int i=1;i<=n;i++) scanf("%d",&w[i]);
     91         for(int i=1;i<=r;i++)
     92         {
     93             int x,y;
     94             scanf("%d%d",&x,&y);
     95             x++;y++;
     96             ins(x,y);ins(y,x);
     97         }
     98         dfs(1,0);
     99         a1=-Inf;
    100         dp(1,0);
    101         printf("%I64d %I64d
    ",a1,a2);
    102     }
    103     return 0;
    104 }
  • 相关阅读:
    Java多线程系列--“基础篇”11之 生产消费者问题
    Java多线程系列--“基础篇”10之 线程优先级和守护线程
    Java多线程系列--“基础篇”09之 interrupt()和线程终止方式
    Java多线程系列--“基础篇”08之 join()
    Java四种线程池的使用
    数据库索引的实现原理
    Java多线程系列--“基础篇”07之 线程休眠
    Java多线程系列--“基础篇”06之 线程让步
    Java多线程系列--“基础篇”05之 线程等待与唤醒
    Java多线程系列--“基础篇”04之 synchronized关键字
  • 原文地址:https://www.cnblogs.com/KonjakJuruo/p/5785400.html
Copyright © 2020-2023  润新知