传送门

Description

给你一张 n 个点 m 条边的DAG,1 号节点没有入边。再向这个DAG中加入边 x→y ,求形成的新图中以 1 为根的外向树形图数 模 10^9+7 。

Input

输入文件的第一行包含四个整数 n、m、x和y,依次代表枫叶上的穴位数、脉络数,以及要添加的脉络是从穴位 x连向穴位y的。 接下来 m行,每行两个整数,由空格隔开,代表一条脉络。第 i 行的两个整数为ui和vi,代表第 i 条脉络是从穴位 ui连向穴位vi的。

Output

输出一行,为添加了从穴位 x连向穴位 y的脉络后,枫叶上以穴位 1 为根的脉络树的方案数对 1,000,000,007取模得到的结果。

Sample Input

4 4 4 3

1 2

1 3

2 4

3 2

Sample Output

3

HINT

对于所有测试数据,1 <= n <= 100000,n - 1 <= m <= min(200000, n(n -1) / 2),

1 <= x, y, ui, vi <= n。

Solution

直接处理外向树形图的数目比较困难,考虑容斥,用 每个点选一条入边的方案数 减去 每个点选一条入边形成不了外向树形图的方案数 得到答案。

每个点选一条入边的方案数直接求

对于无法形成外向树形图的情况显然是出现了一个环(除自环)而我们知道x和y显然就在环中,那么我们只需要从y到x跑一个拓扑排序+dp求出y到x的路径数所占总路径数的比例即可

Code

//By Menteur_Hxy
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define F(i,a,b) for(register int i=(a);i<=(b);i++)
using namespace std;
typedef long long LL; int read() {
int x=0,f=1; char c=getchar();
while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}
while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
return x*f;
} const int N=100010,MOD=1000000007;
bool vis[N];
LL ans,du[N],f[N],de[N];
vector <int> V[N];
queue <int> Q; LL qpow(LL a,LL b) {
LL t=1;
while(b) {
if(b&1) t=t*a%MOD;
a=a*a%MOD; b>>=1;
}
return t;
} void dfs(int x) {
int siz=V[x].size();
F(i,0,siz-1) if(!vis[V[x][i]]) vis[V[x][i]]=1,dfs(V[x][i]);
} int main() {
int n=read(),m=read(),s=read(),t=read(),u,v;
ans=du[1]=1; du[t]++;
F(i,1,m) u=read(),v=read(),V[u].push_back(v),du[v]++;
F(i,1,n) ans=ans*du[i]%MOD,du[i]=qpow(du[i],MOD-2);
vis[t]=1; dfs(t);
F(i,1,n) {
int siz=V[i].size();
F(j,0,siz-1) if(vis[i]&&vis[v=V[i][j]]) de[v]++;
}
f[t]=du[t]; Q.push(t);
while(!Q.empty()) {
u=Q.front(); Q.pop();
int siz=V[u].size();
F(i,0,siz-1) if(vis[v=V[u][i]]) {
f[v]=(f[v]+f[u]*du[v])%MOD;
de[v]--;
if(!de[v]) Q.push(v);
}
}
printf("%lld",ans*(1-f[s]+MOD)%MOD);
return 0;
}

[luogu3244 HNOI2015] 落忆枫音(容斥原理+拓扑排序)的更多相关文章

  1. 【bzoj4011】[HNOI2015]落忆枫音 容斥原理+拓扑排序+dp

    题目描述 给你一张 $n$ 个点 $m$ 条边的DAG,$1$ 号节点没有入边.再向这个DAG中加入边 $x\to y$ ,求形成的新图中以 $1$ 为根的外向树形图数目模 $10^9+7$ . 输入 ...

  2. [BZOJ4011][HNOI2015]落忆枫音:拓扑排序+容斥原理

    分析 又是一个有故事的题目背景.作为玩过原作的人,看题目背景都快看哭了ToT.强烈安利本境系列,话说SP-time的新作要咕到什么时候啊. 好像扯远了嘛不管了. 一句话题意就是求一个DAG再加上一条有 ...

  3. BZOJ4011:[HNOI2015]落忆枫音(DP,拓扑排序)

    Description 「恒逸,你相信灵魂的存在吗?」 郭恒逸和姚枫茜漫步在枫音乡的街道上.望着漫天飞舞的红枫,枫茜突然问出这样一个问题.  「相信吧.不然我们是什么,一团肉吗?要不是有灵魂……我们也 ...

  4. BZOJ 4011: [HNOI2015]落忆枫音 计数 + 拓扑排序

    Description 「恒逸,你相信灵魂的存在吗?」 郭恒逸和姚枫茜漫步在枫音乡的街道上.望着漫天飞舞的红枫,枫茜突然问出 这样一个问题.  「相信吧.不然我们是什么,一团肉吗?要不是有灵魂……我们 ...

  5. 【题解】 [HNOI2015]落忆枫音 (拓扑排序+dp+容斥原理)

    原题戳我 Solution: (部分复制Navi_Aswon博客) 解释博客中的两个小地方: \[\sum_{\left(S是G中y→x的一条路径的点集\right))}\prod_{2≤j≤n,(j ...

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

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

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

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

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

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

  9. 4011: [HNOI2015]落忆枫音

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

随机推荐

  1. 2.3-STP生成树

    2.3-STP生成树     单点失效(signle point of failure)及其解决方法:     当两个Segement之间只有一条物理连接时就有可能出现单点失效→ 单方面的故障导致全网 ...

  2. nyoj 95

     #include<stdio.h> #include<queue> #include<algorithm> using namespace std; stru ...

  3. CSS制作响应式正方形及其应用

    CSS制作响应式正方形?什么鬼?干嘛用的?干嘛用的没人有每人的需求,本人也正好是由于公司正在做的业务须要,想做个照片展示的功能(当然得符合响应式了).而这个照片展示必须符合下面几点功能:1.用三张图片 ...

  4. JQuery实现复制到剪贴板功能

    在网页中实现复制到剪贴板功能,有两种方法, 第1种方法:使用JavaScript自带的方法,但是这种方法只能在IE下使用. document.execCommand("Copy") ...

  5. oc46--nonatomic, retain

    // // Person.h #import <Foundation/Foundation.h> #import "Room.h" #import "Car. ...

  6. git出错调试

    https://stackoverflow.com/questions/6178401/how-can-i-debug-git-git-shell-related-problems git_trace ...

  7. Android热更新实现原理

    最近Android社区的氛围很不错嘛,连续放出一系列的android动态加载插件和热更新库,这篇文章就来介绍一下Android中实现热更新的原理. ClassLoader 我们知道Java在运行时加载 ...

  8. Coursera Algorithms week3 归并排序 练习测验: Shuffling a linked list

    题目原文: Shuffling a linked list. Given a singly-linked list containing n items, rearrange the items un ...

  9. PCB MS SQL 排序应用(row_number rank dense_rank NTILE PARTITION)

    一.排序前,准备数据 --表变量 ),流程数 int) insert into @table union all union all union all union all --查看一下 select ...

  10. Django day08 多表操作 (三) 基于对象的跨表查询 基于双下划线的多表查询

    一: 基于对象的跨表查询 1. 一对一 正向: 反向: 2. 一对多 正向: 反向: 3.多对多 正向: 反向: 4.*****基于对象的多表查询 二: 基于双下划线的多表查询 1. 连表查询 一对一 ...