3078 仓库

Task
给n个节点中有K个入口的树,求有多少个1~n的排列顺序,顺序遍历每个节点时,都存在都入口到该节点的路径,满足路径上不包含之前遍历过的点。答案mod 1e9+7。
这里写图片描述
Solution
1. K=1。
在树上求方案数,容易想到是树形dp。
以入口S作为根,发现遍历节点x之前,x的子树必须都已经被遍历过了,dp[ i ]表示,以i为根的子树都已经被遍历的方案数。X子树对应的序列为儿子们t1,t2~tn的序列的组合。保持各小序列相对位置不变,穿插组合成一个大序列,再在结尾加上x的序列。用排列组合(乘法逆元和快速幂)来实现。

  1. K=2序列上的问题
    a) 是一条链,且S1,S2在链的两端。
    定义dp[ l ][ r ]为[ l , r ]这个区间都被遍历的方案数,如果端点L,R都被遍历了,那么L,R里面的点也被遍历了。
    最后一个点取的只可能是l或r.
    dp[ l ][ r ]=dp[ l+1 ][ r ]+dp[ l ][ r-1 ]
    特别的,当l=r时dp[ l ][ r ]=1
    b) 是一棵树。
    以S1,S2为两端,把树拉成一条链,链上的每一个点代表一棵树。
    对于链上的每一个点,先用K=1的树形dp预处理出这棵树的方案数,dp[i].
    最后一个取的只可能是L上的根或者R上的根,记为rt,但是rt下的节点,却可以与之前的序列任意组合。
    DP[ l ][ R ]=C( sum( L, R )-1,sum( L,L )-1 )*DP[ L+1 ][ R ]*dp[ id [ L ] ]+
    C ( sum(L,R )- 1,sum( R,R )- 1 )*DP[ L+1 ][ R ] *dp[ id [R] ]
    这里写图片描述
const int M=1e5+5,N=2e3+3,P=1e9+7;
int n,m,ecnt,S1,S2;
int head[M],f[M];
struct edge{
    int t,nxt;
}e[M<<1];
inline void addedge(int f,int t){
    e[++ecnt]=(edge){t,head[f]};
    head[f]=ecnt;
}
inline void input(){
    int i,j,k,a,b;
    rd(n);rd(m);
    rd(S1);
    if(m==2)rd(S2);
    rep(i,1,n-1){
        rd(a);rd(b);
        addedge(a,b);
        addedge(b,a);
    }
}
inline void init(){
    int i;
    f[0]=1;
    rep(i,1,n)f[i]=1ll*f[i-1]*i%P;
}
inline int fst_pow(int a,int p){
    int ans=1;
    while(p){
        if(p&1)ans=1ll*ans*a%P;
        a=1ll*a*a%P;
        p>>=1;
    }
    return ans;
}
inline int C(int a,int b){return 1ll*f[a]*fst_pow(1ll*f[b]*f[a-b]%P,P-2)%P;}
struct P40{//树形dp[i],i子树内被填满 排序的方案数 
    int dp[M],sz[M];
    inline void dfs(int f,int x){
        dp[x]=1;
        for(int i=head[x];i;i=e[i].nxt){
            if(e[i].t==f)continue;
            dfs(x,e[i].t);
            sz[x]+=sz[e[i].t];
            dp[x]=1ll*dp[x]*dp[e[i].t]%P*C(sz[x],sz[e[i].t])%P; 
        }
        sz[x]++;
    }
    inline void solve(){
        dfs(0,S1);
        sc(dp[S1]);
    }
}P40;
struct P60{
    int dp[N],DP[N][N],sum[N],fa[N],id[N],sz[N];
    int num;
    bool mark[N];
    inline void dfs1(int f,int x){
        fa[x]=f;
        for(int i=head[x];i;i=e[i].nxt)if(e[i].t!=f)dfs1(x,e[i].t);
    }
    inline void getarray(){
        int i,x=S1;
        while(x!=fa[S2]){
            mark[x]=1;//标记序列上的点 
            id[++num]=x;//重新编号 
            x=fa[x];
        }
    }
    inline void dfs2(int f,int x){
        dp[x]=1;
        for(int i=head[x];i;i=e[i].nxt){
            if(e[i].t==f||mark[e[i].t])continue;
            dfs2(x,e[i].t);
            sz[x]+=sz[e[i].t];
            dp[x]=1ll*dp[x]*dp[e[i].t]%P*C(sz[x],sz[e[i].t])%P;
        }
        sz[x]++;
    }
    inline void solve(){
        int i,j,k,l,r;
        dfs1(0,S2);
        getarray();
        rep(i,1,num){
            dfs2(0,id[i]);//序列上的一个点就是一棵树
            sum[i]=sum[i-1]+sz[id[i]];//前缀和 
            DP[i][i]=dp[id[i]];
        }
        rep(i,2,num)
            rep(l,1,num-i+1){
                r=l+i-1;
                DP[l][r]=1ll*DP[l+1][r]*DP[l][l]%P*C(sum[r]-sum[l-1]-1,sum[l]-sum[l-1]-1)%P+1ll*DP[l][r-1]*DP[r][r]%P*C(sum[r]-sum[l-1]-1,sum[r]-sum[r-1]-1)%P;
                if(DP[l][r]>=P)DP[l][r]-=P;
            }
        sc(DP[1][num]);
    }
}P60;
int main(){
//  freopen("0.in","r",stdin);
    input();
    init();
    if(m==1)P40.solve();
    else P60.solve();
    return 0;
}
Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值