其他分享
首页 > 其他分享> > 洛谷 4099 [HEOI2013]SAO——树形DP

洛谷 4099 [HEOI2013]SAO——树形DP

作者:互联网

题目:https://www.luogu.org/problemnew/show/P4099

结果还是看了题解才会……

关键是状态,f[ i ][ j ] 表示 i 子树、 i 号点是第 j 个出现的方案数。

合并的时候,很重要的是去枚举孩子 v 有 k 个点放在了第 i 个点前面。这样 v 可以在的位置就根据该边是 > 还是 < 而是一个前/后缀。这样就是 n2 的了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
int rdn()
{
  int ret=0;bool fx=1;char ch=getchar();
  while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
  while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
  return fx?ret:-ret;
}
int Mn(int a,int b){return a<b?a:b;}
const int N=1005,mod=1e9+7;
int upt(int x){while(x>=mod)x-=mod;while(x<0)x+=mod;return x;}

int n,siz[N],c[N][N],f[N][N],pr[N][N],sc[N][N];
int hd[N],xnt,to[N<<1],nxt[N<<1];bool lx[N<<1];//1:<
char ch;
void add(int x,int y,bool fx)
{ to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;lx[xnt]=fx;}
void dfs(int cr,int fa)
{
  siz[cr]=1; f[cr][1]=1;//
  for(int i=hd[cr],v;i;i=nxt[i])
    if((v=to[i])!=fa)
      {
    dfs(v,cr); siz[cr]+=siz[v];
    for(int j=siz[cr];j;j--)
      {
        int lj=0;
        for(int k=0,l2=Mn(j-1,siz[v]);k<=l2;k++)
          {
        int tp=0;
        if(lx[i]) tp=(ll)f[cr][j-k]*sc[v][k+1]%mod;
        else tp=(ll)f[cr][j-k]*pr[v][k]%mod;
        tp=(ll)tp*c[j-1][k]%mod*c[siz[cr]-j][siz[v]-k]%mod;
        lj=upt(lj+tp);
          }
        f[cr][j]=lj;
      }
      }
  pr[cr][0]=sc[cr][siz[cr]+1]=0;///
  for(int j=1;j<=siz[cr];j++)
    {
      pr[cr][j]=upt(pr[cr][j-1]+f[cr][j]);
    }
  for(int j=siz[cr];j;j--)
    {
      sc[cr][j]=upt(sc[cr][j+1]+f[cr][j]);
    }
  pr[cr][0]=sc[cr][siz[cr]+1]=0;
}
int main()
{
  int T=rdn(),lm=1000;
  for(int i=0;i<=lm;i++)c[i][0]=1;
  for(int i=1;i<=lm;i++)
    for(int j=1;j<=i;j++)
      c[i][j]=upt(c[i-1][j]+c[i-1][j-1]);
  while(T--)
    {
      n=rdn(); memset(hd,0,sizeof hd); xnt=0;
      for(int i=1,u,v;i<n;i++)
    {
      u=rdn()+1;cin>>ch;v=rdn()+1;
      add(u,v,ch=='<'); add(v,u,ch=='>');
    }
      dfs(1,0);
      printf("%d\n",sc[1][1]);
    }
  return 0;
}

 

标签:ch,SAO,个点,int,4099,long,while,HEOI2013,include
来源: https://www.cnblogs.com/Narh/p/10883794.html