[BZOJ4011][HNOI2015]落忆枫音:拓扑排序+容斥原理
分析
又是一个有故事的题目背景。作为玩过原作的人,看题目背景都快看哭了ToT。强烈安利本境系列,话说SP-time的新作要咕到什么时候啊。
好像扯远了嘛不管了。
一句话题意就是求一个DAG再加上一条有向边所构成的有向图的以\(1\)为根的外向树形图的个数。
考虑一个DAG的情况,答案显然是:
\]
其中\(in[i]\)表示结点\(i\)的入度,这个式子的意思就是给每个非根结点选一条入边。由于是DAG所以这样构造出来的一定是一个外向树形图。
加入一条边后,图上可能会出现环,如果有一些结点选择的入边正好构成一个环的话,那么这样构造出的图是不合法的。
而每个这样的环会让答案减去\(\frac{\prod_{i=2}^{n}in[i]}{\prod_{i在环上}in[i]}\)。
设新加入的边为\(s \to t\),考虑到每个环都是由原图中\(t\)到\(s\)的一条路径加上\(s \to t\)这条新加入的边构成的,所以我们就可以通过拓扑排序统计那个东西了。
时间复杂度可以做到\(O(n)\)。(不过博主因为快速幂算逆元多了个\(\log\))
代码
#include <bits/stdc++.h>
#define rin(i,a,b) for(register int i=(a);i<=(b);++i)
#define irin(i,a,b) for(register int i=(a);i>=(b);--i)
#define trav(i,a) for(register int i=head[a];i;i=e[i].nxt)
typedef long long LL;
using std::cin;
using std::cout;
using std::endl;
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*10+ch-'0';ch=getchar();}
return x*f;
}
const int MAXN=100005;
const int MAXM=200005;
const LL MOD=1e9+7;
int n,m,s,t,ecnt,head[MAXN];
int out[MAXN],in[MAXN];
LL f[MAXN];
std::queue<int> q;
struct Edge{
int to,nxt;
}e[MAXM];
inline void add_edge(int bg,int ed){
++ecnt;
e[ecnt].to=ed;
e[ecnt].nxt=head[bg];
head[bg]=ecnt;
}
inline LL qpow(LL x,LL y){
LL ret=1,tt=x%MOD;
while(y){
if(y&1) ret=ret*tt%MOD;
tt=tt*tt%MOD;
y>>=1;
}
return ret;
}
LL topo(){
while(!q.empty()) q.pop();
rin(i,1,n)
if(!out[i])
q.push(i);
f[s]=1;
while(!q.empty()){
int x=q.front();q.pop();
f[x]=f[x]*qpow(in[x],MOD-2)%MOD;
trav(i,x){
int ver=e[i].to;
--out[ver];
if(!out[ver]) q.push(ver);
f[ver]=(f[ver]+f[x])%MOD;
}
if(x==t) return f[x];
}
}
int main(){
n=read(),m=read(),s=read(),t=read();
++in[t];
rin(i,1,m){
int u=read(),v=read();
++out[u],++in[v];
add_edge(v,u);
}
LL ans=1;
rin(i,2,n) ans=ans*in[i]%MOD;
if(t==1){
printf("%lld\n",ans);
return 0;
}
ans=(ans-topo()*ans%MOD+MOD)%MOD;
printf("%lld\n",ans);
return 0;
}
[BZOJ4011][HNOI2015]落忆枫音:拓扑排序+容斥原理的更多相关文章
- bzoj4011 [HNOI2015]落忆枫音 拓扑排序+DP
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4011 题解 首先考虑如果没有那么一条被新加进来的奇怪的边的做法. 我们只需要给每一个点挑一个父 ...
- bzoj4011[HNOI2015]落忆枫音 dp+容斥(?)
4011: [HNOI2015]落忆枫音 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1125 Solved: 603[Submit][Statu ...
- BZOJ4011:[HNOI2015]落忆枫音(DP,拓扑排序)
Description 「恒逸,你相信灵魂的存在吗?」 郭恒逸和姚枫茜漫步在枫音乡的街道上.望着漫天飞舞的红枫,枫茜突然问出这样一个问题. 「相信吧.不然我们是什么,一团肉吗?要不是有灵魂……我们也 ...
- BZOJ4011 HNOI2015落忆枫音(动态规划+拓扑排序)
DAG中每个点选一条入边就可以构成一棵有向树,所以如果没有环答案就是∏degreei. 考虑去掉含环的答案.可以看做把环缩点,剩下的点仍然可以任意选入边.于是去除的方案数即为∏degreei/∏deg ...
- BZOJ4011: [HNOI2015]落忆枫音
Description 「恒逸,你相信灵魂的存在吗?」 郭恒逸和姚枫茜漫步在枫音乡的街道上.望着漫天飞舞的红枫,枫茜突然问出 这样一个问题. 「相信吧.不然我们是什么,一团肉吗?要不是有灵魂……我们 ...
- [BZOJ4011][HNOI2015]落忆枫音-[dp乱搞+拓扑排序]
Description 传送门 Solution 假如我们的图为DAG图,总方案数ans为每个点的入度In相乘(不算1号点).(等同于在每个点的入边选一条边,最后一定构成一棵树). 然而如果加了边x- ...
- [BZOJ4011][HNOI2015] 落忆枫音(学习笔记) - 拓扑+DP
其实就是贴一下防止自己忘了,毕竟看了题解才做出来 Orz PoPoQQQ 原文链接 Description 背景太长了 给定一个DAG,和一对点(x, y), 在DAG中由x到y连一条有向边,求生成树 ...
- luogu3244 bzoj4011 HNOI2015 落忆枫音
这道题目题面真长,废话一堆. 另外:这大概是我第一道独立做出来的HNOI2011年以后的题目了吧.像我水平这么差的都能做出来,dalao您不妨试一下自己想想? 题目大意:给一个DAG,其中1号点没有入 ...
- BZOJ4011: [HNOI2015]落忆枫音(dp 乘法原理)
题意 题目链接 Sol 非常妙的一道题 设\(inder[i]\)表示\(i\)号节点的度数 首先如果是个DAG的话,可以考虑在每个点的入边中选一条边作为树形图上的边,这样\(ans = \prod_ ...
随机推荐
- redis 小结二
1.在redis客户端获取redis 配置文件的某个配置信息(需要先打开redis客户端) config get 配置项 , 如果要列出所有的配置项( CONFIG GET *) 2.在redis ...
- 3-app应用操作——Models.py和字段类型
Models.py定义 每一个数据表对应一个model定义,model之间和java一样可以相互之间继承.所有的model都必须继承 from django.db import models#或间接继 ...
- docker无法删除<none>镜像
.进入root权限 sudo su # 或 sudo -i .停止所有的container(这样才能够删除其中的images): docker stop $(docker ps -a -q) 如果想要 ...
- python:count 函数
API 一.string 中 某字符 的次数 str.count(sub, start= 0,end=len(string)) Args Annotations sub 搜索的子字符串 start 字 ...
- 我所不知的JS
几天前在阅读 MDN 文档时我发现了一些我从来不知道的 JS 特性和 API. 下面是一份简短的清单, 无论有用不有用——学习 JS 的道路似乎是没有尽头的. 标签语句 在 JS 中,你可以对 for ...
- JVM内存结构思维导图
- _proto_和prototype的区别
1. _proto_和prototype prototype属性是一个静态属性, _proto_属性是一个实例属性. prototype表示类的原型对象,_proto_表示原型对象中定义的内部属性[p ...
- Vue配置bs环境
安装插件 jQuery >: cnpm install jquery vue/cli 3 配置jQuery:在vue.config.js中配置(没有,手动项目根目录下新建) const webp ...
- 缺少库libresolv
"_dns_free_resource_record", referenced from: -[xxxx processRecord:length:] in xxx.a(xxx.o ...
- windows核心编程01_错误处理
windows函数调用出错时,可以通过方法去查询出错根源在哪里. #include <Windows.h> #include <iostream> using namespac ...