题目大意就是 给你一个DAG

然后添加一条边\(x->y\) ,询问以1为根的生成树的个数

QWQ

首先假设没有添加的边

答案就应该是

\[ans=\prod_{i=1}^{n} in[i]
\]

QWQ就相当于每个点选择一个父亲。

那么加入一条边,我们会有一些不合法的情况,那就是包含一条\(y->x\)路径,剩下随便选的方案数。假设全集是\(C\),然后路径上的点的集合是\(S\),那我们实际上求的就是$$\frac{F(C)}{F(S)}$$

其中\(F(S)\)表示\(S\)集合中所有点的入度的乘积

然后对于这个东西,我们可以考虑拓扑图上dp的方式

来解决

//假设我们添加了一条x->y的边,要想不合法,就是求y->x的路径条数
//所以我们要将令起点,也就是y的初值f[y]=ans void addedge(int x,int y)
{
nxt[++cnt]=point[x];
to[cnt]=y;
in[y]++;
point[x]=cnt;
} int qsm(int i,int j)
{
int ans=1;
while (j)
{
if (j&1) ans=ans*i%mod;
i=i*i%mod;
j>>=1;
}
return ans;
} void tpsort()
{
//cout<<ans<<endl;
for (int i=1;i<=n;i++)
{
if (!in[i]) q.push(i);
}
while (!q.empty())
{
int now = q.front();
q.pop();
//cout<<now<<endl;
//int ymh=0;
//if (now==y) ymh=1;
f[now]=f[now]*qsm(d[now],mod-2)%mod; //cout<<now<<" "<<f[now]<<endl;
for (int i=point[now];i;i=nxt[i])
{
int p =to[i];
in[p]--;
f[p]=(f[p]+f[now])%mod;
if (!in[p]) q.push(p);
}
}
}

下面是整个的代码

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define mk makr_pair
#define ll long long
#define int long long using namespace std; inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
} const int maxn = 2e5+1e2;
const int maxm = 2*maxn;
const int mod = 1e9+7; int point[maxn],nxt[maxm],to[maxm];
int n,m;
int cnt,in[maxn];
queue<int> q;
int ans;
int f[maxn];
int x,y;
int d[maxn]; //假设我们添加了一条x->y的边,要想不合法,就是求y->x的路径条数
//所以我们要将令起点,也就是y的初值f[y]=ans void addedge(int x,int y)
{
nxt[++cnt]=point[x];
to[cnt]=y;
in[y]++;
point[x]=cnt;
} int qsm(int i,int j)
{
int ans=1;
while (j)
{
if (j&1) ans=ans*i%mod;
i=i*i%mod;
j>>=1;
}
return ans;
} void tpsort()
{
//cout<<ans<<endl;
for (int i=1;i<=n;i++)
{
if (!in[i]) q.push(i);
}
while (!q.empty())
{
int now = q.front();
q.pop();
//cout<<now<<endl;
//int ymh=0;
//if (now==y) ymh=1;
f[now]=f[now]*qsm(d[now],mod-2)%mod; //cout<<now<<" "<<f[now]<<endl;
for (int i=point[now];i;i=nxt[i])
{
int p =to[i];
in[p]--;
f[p]=(f[p]+f[now])%mod;
if (!in[p]) q.push(p);
}
}
} signed main()
{
n=read(),m=read(),x=read(),y=read();
for (int i=1;i<=m;i++)
{
int u=read(),v=read();
addedge(u,v);
}
ans=1;
for (int i=2;i<=n;i++)
{
if (i==y) ans=ans*(in[i]+1)%mod,d[i]=in[i]+1;
else ans=ans*in[i]%mod,d[i]=in[i];
}
f[y]=ans;
if (x==1)
{
cout<<ans<<"\n";
return 0;
}
tpsort();
cout<<(ans-f[x]+mod)%mod<<endl;
return 0;
}

洛谷3244 落忆枫音 (拓扑图dp+式子)的更多相关文章

  1. 洛谷P3244 落忆枫音 [HNOI2015] 拓扑排序+dp

    正解:拓扑排序+dp 解题报告: 传送门 我好暴躁昂,,,怎么感觉HNOI每年总有那么几道题题面巨长啊,,,语文不好真是太心痛辣QAQ 所以还是要简述一下题意,,,就是说,本来是有一个DAG,然后后来 ...

  2. P3244-[HNOI2015]落忆枫音【dp】

    正题 题目链接:https://www.luogu.com.cn/problem/P3244 题目大意 给出一个\(\text{DAG}\),保证\(1\)可以到达所有点.然后再加入一条边(之后不一定 ...

  3. 【BZOJ4011】【HNOI2015】落忆枫音(动态规划)

    [BZOJ4011][HNOI2015]落忆枫音(动态规划) 题面 BZOJ 洛谷 Description 「恒逸,你相信灵魂的存在吗?」 郭恒逸和姚枫茜漫步在枫音乡的街道上.望着漫天飞舞的红枫,枫茜 ...

  4. 【BZOJ】【4011】【HNOI2015】落忆枫音

    拓扑排序+DP 题解:http://blog.csdn.net/PoPoQQQ/article/details/45194103 http://www.cnblogs.com/mmlz/p/44487 ...

  5. BZOJ 4011: [HNOI2015]落忆枫音( dp )

    DAG上有个环, 先按DAG计数(所有节点入度的乘积), 然后再减去按拓扑序dp求出的不合法方案数(形成环的方案数). ---------------------------------------- ...

  6. bzoj4011[HNOI2015]落忆枫音 dp+容斥(?)

    4011: [HNOI2015]落忆枫音 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1125  Solved: 603[Submit][Statu ...

  7. [HNOI2015]落忆枫音 解题报告

    [HNOI2015]落忆枫音 设每个点入度是\(d_i\),如果不加边,答案是 \[ \prod_{i=2}^nd_i \] 意思是我们给每个点选一个父亲 然后我们加了一条边,最后如果还这么统计,那么 ...

  8. 4011: [HNOI2015]落忆枫音

    4011: [HNOI2015]落忆枫音 链接 分析: 原来是一个DAG,考虑如何构造树形图,显然可以给每个点找一个父节点,所以树形图的个数就是$\prod\limits_u deg[u]$. 那么加 ...

  9. BZOJ 4011 【HNOI2015】 落忆枫音

    题目链接:落忆枫音 以下内容参考PoPoQQQ大爷的博客 首先我们先来考虑一下如果没有新加入的那条边,答案怎么算. 由于这是一个\(DAG\),所以我们给每个点随便选择一条入边,最后一定会构成一个树形 ...

随机推荐

  1. ES6对象扩展——部分新的方法和属性

    1.Object.is方法返回布尔值,和全等于===差不多,除了参数是+0和-0,以及NaN时 //Object.is,返回布尔值,和全等于===差不多,除了+0和-0,以及NaN console.l ...

  2. 一种封装Retrofit的方法,可以自动解析Gson,回避Method return type must not include a type variable or wildcard: retrofit2.Call<T>的问题

    封装目的:屏蔽底层实现,提供统一接口,并支持Gson自动转化 最初封装: //请求方法 interface RequestListener { interface PostListener { @PO ...

  3. vue 封装 axios 和 各类的请求,以及引入 .vue 文件中使用

    //src 底下建立 api 文件夹 // api 文件夹下建立 request,js 文件,文件内容复制下面这段代码即可   /**  * ajax请求配置  */ import axios fro ...

  4. K8S命令行工具——kubectl

    1.kubectl概述 2.kubectl命令的语法 例子: 3.kubectl子命令使用分类 (1)基础命令 (2)部署和集群管理命令 (3)故障和调试命令 (4)其他命令 4.kubectl命令例 ...

  5. 即时通讯网-TCPIP族关系图

  6. sqlite数据库的基本用法及C语言的API接口简介

    ********************sqlite数据库******************** http://www.sqlite.org/c3ref/intro.html 1-- 安装数据库: ...

  7. Nginx+Tomcat 负载均衡、动静分离集群

    目录: 一.Nginx负载均衡实现原理 二.Nginx动静分离实现原理 三.Nginx+Tomcat 负载均衡.动静分离集群部署 一.Nginx负载均衡实现原理 1.Nginx实现负载均衡是通过反向代 ...

  8. vim中字符串的替换

    vi/vim 中可以使用 :s 命令来替换字符串 :s/vivian/sky/ 替换当前行第一个 vivian 为 sky :s/vivian/sky/g 替换当前行所有 vivian 为 sky : ...

  9. Django学习day10随堂笔记

    每日测验 """ 今日考题 1.默写ajax基本语法,及提交json数据和文件都需要添加哪些额外参数 2.什么是序列化,截止目前为止你所接触过的序列化有哪些 3.批量插入 ...

  10. 概述 .NET 6 ThreadPool 实现

    目录 前言 任务的调度 基本调度单元 IThreadPoolWorkItem 实现类的实例. Task 全局队列 本地队列 偷窃机制 Worker Thread 的生命周期管理 线程生命注入实验 .N ...