[HDU multi-school] Ridiculous Netizens

[HDU multi-school] Ridiculous Netizens

  • Dotted rule
    • Divided into two portions: a certain point P, through the communication block P with or without P.
    • After dependency tree using backpack P
    • Without partial recursive calculation of P
  • Tree dependent backpack
    • v points must be transferred from point u by his father
    • I.e., it must pass through the point P
    • \(dp[v][s*a[v]]+=dp[u][s]\)
    • The second dimension representing the product of the communication block
    • The first dimension representing the number of the program passes through the point P and a certain point
    • So in the end the parent node plus the number of sub-node solution
  • Space Optimization
    • The second dimension is not that big
    • Slightly change the meaning, but also into a "hold" how much volume
    • \ (\ lfloor \ frac {m } {s} \ rfloor \) can be divided into a number of equivalent state
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 2010;
const int mod = 1e9+7;
struct edge{
    int to,next;
}e[maxn<<1];
ll val[maxn],kuai[maxn];
ll dp[maxn][maxn];
int nowN,rt,maxP,head[maxn],tol,cnt,n;
int Size[maxn];
bool vis[maxn<<1];
ll ans;
int m;
inline void Mod(ll &a,ll b){
   a=a+b<mod?a+b:a+b-mod;
}
void init(int n){
    tol=1;
    for(int i=0;i<=n;++i){
        head[i]=0;
    }
    rt=0;
    cnt=ans=0;
}
void add(int u,int v){
    tol++;
    vis[tol]=0;
    e[tol].to=v;
    e[tol].next=head[u];
    head[u]=tol;
}
void get_rt(int u,int fa){
   int max_part=0;
   Size[u]=1;
   for(int i=head[u],v;i;i=e[i].next){
      v=e[i].to;
      if(vis[i]||v==fa)continue;
      get_rt(v,u);
      Size[u]+=Size[v];
      max_part=max(max_part,Size[v]);
   }
   max_part=max(nowN-Size[u],max_part);
   if(max_part<maxP){
     maxP=max_part;
     rt=u;
   }
}
void dfs(int u,int fa){
   for(int i=1;i<=cnt;++i) dp[u][i]=0;
   ll k=val[u],t;
   for(int i=1,j=1;i<=cnt;++i){
        t=kuai[i]/k;
        if(t==0)break;
        while(kuai[j]>t)++j;
        Mod(dp[u][j],dp[fa][i]);
   }
   for(int i=head[u],v;i;i=e[i].next){
      if(vis[i]) continue;
      v=e[i].to;
      if(v==fa) continue;
      dfs(v,u);
      for(int j=1;j<=cnt;++j) Mod(dp[u][j],dp[v][j]);
   }
}
void calc(){
   dp[0][1]=1;
   dfs(rt,0);
   for(int i=1;i<=cnt;++i) Mod(ans,dp[rt][i]);
   for(int i=head[rt],v;i;i=e[i].next){
       if(vis[i])continue;
       v=e[i].to;
       vis[i^1]=1;
       nowN=Size[v];
       maxP=n+5;
       rt=0;
       get_rt(v,0);
       calc();
   }
}
int main(){
    int _;
    scanf("%d",&_);
    while(_--){
        scanf("%d%d",&n,&m);
        init(n);
        for(int i=1;i<=n;++i)scanf("%lld",&val[i]);
        for(int i=1;i<=m;i=m/(m/i)+1){
            kuai[++cnt]=m/i;
        }
        for(int i=1,u,v;i<n;++i){
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        nowN=n;
        maxP=n+5;
        get_rt(1,1);
        calc();
        printf("%lld\n",ans);
    }
    return 0;
}

The amount of code is concentrated at the point of partition, but you can set team

DP is well understood.

Guess you like

Origin www.cnblogs.com/smallocean/p/11355396.html