zoukankan      html  css  js  c++  java
  • 【BZOJ4011】[HNOI2015] 落忆枫音(DAG上记忆化搜索)

    点此看题面

    大致题意: 在一张(DAG)(其中(1)号点入度为(0))上加一条边,求以(1)为根的有向生成树个数。

    前言

    这道题基本上都是自己做出来的,应该还是一道比较简单的题目吧。

    考虑不加边

    首先,我们考虑不加边的情况。

    则显然,对于一个点(i),它的父节点有(deg_i)种选择方式。

    因此,答案为(prod_{i=2}^ndeg_i)

    加边需减去的答案

    再考虑加上一条边,和不加边的情况相比,若以同样的方式计算答案,这种情况下可能出现的问题就是会出现环。

    因此,我们只要减去环的情况数,是不是就可以了呢?

    而环的情况数怎么算?

    对于一个环,显然环上的点有唯一选择,而环外的点可以任意选择,即:

    [prod_{i ot∈Circle}deg_i ]

    而若我们设(p=prod_{i=2}^ndeg_i),则这就相当于是:

    [frac p{prod_{i∈Circle}deg_i} ]

    因此,设新增的边为(s)(t)的一条边,则我们只要从(t)(s)进行(dfs),然后记忆化搜索记下每一个点到(s)的答案即可。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 100000
    #define M 200000
    #define X 1000000007
    #define add(x,y) (e[++ee].nxt=lnk[x],++deg[e[lnk[x]=ee].to=y])
    #define Inc(x,y) ((x+=(y))>=X&&(x-=X))
    using namespace std;
    int n,m,s,t,p,f[N+5],ee,lnk[N+5],deg[N+5];struct edge {int to,nxt;}e[M+5];
    class FastIO
    {
    	private:
    		#define FS 100000
    		#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
    		#define tn (x<<3)+(x<<1)
    		#define D isdigit(c=tc())
    		char c,*A,*B,FI[FS];
    	public:
    		I FastIO() {A=B=FI;}
    		Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
    }F;
    I int Qpow(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}
    I int dfs(CI x)//记忆化搜索
    {
    	if(x==s) return 1LL*p*Qpow(deg[x],X-2)%X;if(~f[x]) return f[x];RI i,res=0;
    	for(i=lnk[x];i;i=e[i].nxt) Inc(res,dfs(e[i].to));return f[x]=1LL*res*Qpow(deg[x],X-2)%X;//统计后续答案,并除以当前点度数
    }
    int main()
    {
    	RI i,x,y;F.read(n),F.read(m),F.read(s),F.read(t),++deg[t];//注意增加t号点入度
    	for(i=1;i<=m;++i) F.read(x),F.read(y),add(x,y);for(p=1,i=2;i<=n;++i) p=1LL*p*deg[i]%X;//统计度数积
    	return memset(f,-1,sizeof(f)),printf("%d",t^1?(p-dfs(t)+X)%X:p),0;//特判t=1是无用边
    }
    
  • 相关阅读:
    2019.4.18 淘宝商品显示块2号铺设练习
    Debuggee not connected 寒江孤钓<<windows 内核安全编程>> 学习笔记
    指定的服务已标记为删除 寒江孤钓<<windows 内核安全编程>> 学习笔记
    删除自定义服务 寒江孤钓<<windows 内核安全编程>> 学习笔记
    发生系统错误 1275.此驱动程序被阻止加载 寒江孤钓<<windows 内核安全编程>> 学习笔记
    无法编译出.sys文件 寒江孤钓<<windows 内核安全编程>> 学习笔记
    iOS11 适配
    curl
    ddd
    201060512 viewcontroller view
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ4011.html
Copyright © 2011-2022 走看看