bzoj 4011
看了好多篇题解才看懂的题,我实在太菜了...
首先根据一个我不知道的算法,可以证明在没有加入新的边的时候,原图的所有生成树的方案数就是所有点(除1以外)的度之积
那么在新加入这条边之后,我们仍然可以这样计算,但是会产生一种问题:就是会出现环!
所以我们需要利用一些容斥,把不合法的情况去掉
接下来我们考虑如何算出不合法的情况
由于原图是一个有向无环图,所以在原图中怎么选都不会出现环,所以多的一条边一定在环内!
那么如果出现了环,一定是从多的边的终点到起点的一条路径
所以我们只需要找出终点到起点的路径数量即可
那么就进行一个拓扑排序求一下即可
考虑一下怎么求:
首先记状态:dp[i]表示从终点到i的路径数量
然后考虑初值:dp[ed]=初始方案/终点入度
(关于这里为什么要除掉一个入度:因为原来的初始方案中是包含这一点的入度的,所以要除掉这个入度)
最后ans去掉这一部分即可
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#define mode 1000000007
#define ll long long
using namespace std;
struct Edge
{
int next;
int to;
}edge[200005];
int n,m,st,ed;
ll inr[100005];
ll rinr[100005];
int head[100005];
ll inv[300005];
int cnt=1;
ll ans=1;
ll dp[100005];
void init()
{
inv[0]=inv[1]=1;
for(int i=2;i<=300000;i++)
{
inv[i]=(mode-mode/i)*inv[mode%i]%mode;
}
memset(head,-1,sizeof(head));
cnt=1;
}
void add(int l,int r)
{
edge[cnt].next=head[l];
edge[cnt].to=r;
head[l]=cnt++;
}
ll bfs()
{
dp[ed]=ans;
queue <int> M;
for(int i=1;i<=n;i++)
{
if(!inr[i])
{
M.push(i);
}
}
while(!M.empty())
{
int u=M.front();
M.pop();
dp[u]*=inv[rinr[u]];
dp[u]%=mode;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int to=edge[i].to;
dp[to]+=dp[u];
dp[to]%=mode;
inr[to]--;
if(!inr[to])
{
M.push(to);
}
}
}
return ((ans-dp[st])%mode+mode)%mode;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&st,&ed);
init();
rinr[ed]=1;
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
inr[y]++;
rinr[y]++;
}
for(int i=2;i<=n;i++)
{
ans*=rinr[i];
ans%=mode;
}
if(ed==1)
{
printf("%lld\n",ans);
}else
{
printf("%lld\n",bfs());
}
return 0;
}
bzoj 4011的更多相关文章
- BZOJ 4011: [HNOI2015]落忆枫音( dp )
DAG上有个环, 先按DAG计数(所有节点入度的乘积), 然后再减去按拓扑序dp求出的不合法方案数(形成环的方案数). ---------------------------------------- ...
- BZOJ 4011 HNOI2015 落忆枫音 DAG上的dp(实际上重点在于分析)
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4011 题意概述:给出一张N点的DAG(从1可以到达所有的点),点1的入度为0.现在加一条原 ...
- BZOJ 4011 HNOI2015 落忆枫音
AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=4011 题目很长,写得也很有诗意与浪漫色彩,让我们不禁感叹出题人是一个多么英俊潇洒的人. 所 ...
- BZOJ 4011 落忆枫音
几个重点: 1.从每个点任选一条入边,都可以成为一个树形图. 2.于是考虑所有答案减去有环的答案. 3.将要求的东西形式化表示出来,然后发现可以直接dp.. 好厉害啊.. #include<io ...
- BZOJ 4011 开店
Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的想法当然非常好啦,但是她们也发现她们 ...
- BZOJ 4011 【HNOI2015】 落忆枫音
题目链接:落忆枫音 以下内容参考PoPoQQQ大爷的博客 首先我们先来考虑一下如果没有新加入的那条边,答案怎么算. 由于这是一个\(DAG\),所以我们给每个点随便选择一条入边,最后一定会构成一个树形 ...
- BZOJ 4011: [HNOI2015]落忆枫音 计数 + 拓扑排序
Description 「恒逸,你相信灵魂的存在吗?」 郭恒逸和姚枫茜漫步在枫音乡的街道上.望着漫天飞舞的红枫,枫茜突然问出 这样一个问题. 「相信吧.不然我们是什么,一团肉吗?要不是有灵魂……我们 ...
- Week One
2018.11.21: 1.[BZOJ 4868][SHOI 2017] 从后往前枚举最后位置即可,如果$A<B$,用尽可能多的$A$替换$B$操作 Tip:很大的$C$可能爆$longlong ...
- 【BZOJ】【4011】【HNOI2015】落忆枫音
拓扑排序+DP 题解:http://blog.csdn.net/PoPoQQQ/article/details/45194103 http://www.cnblogs.com/mmlz/p/44487 ...
随机推荐
- redis架构~哨兵模式
一 哨兵模式稳定版本 redis哨兵模式是redis自带的高可用框架,稳定版本为redis2.8以上二 哨兵模式建立 1 避免单点故障,建立启动多个哨兵进程 2 哨兵模式启动命令 redis-s ...
- MatrixBG 代码瀑布的实现
黑客帝国中代码瀑布是怎么实现的呢? 我们可以通过 window.innerWidth获取屏幕的宽度W,并规定字符的大小size,那么屏幕中共有 W/size 列字符出现, 我们不断的去更改每一列中文字 ...
- Anaconda使用总结
序 Python易用,但用好却不易,其中比较头疼的就是包管理和Python不同版本的问题,特别是当你使用Windows的时候.为了解决这些问题,有不少发行版的Python,比如WinPython.An ...
- kali linux 安装 matlab2016Rb
分享安装包: https://pan.baidu.com/s/1hrBd3Li 密码:u9q3 由于Linux版的分为两个镜像,需要挂载后合并: mount R2016b_glnxa64_dvd1.i ...
- cartographer 分析
原文链接:http://blog.csdn.net/zyh821351004/article/details/52421005 cartographer与karto的比较 1. 两者采取的都是图优化框 ...
- 【转】python 内置函数总结(大部分)
[转]python 内置函数总结(大部分) python 内置函数大讲堂 python全栈开发,内置函数 1. 内置函数 python的内置函数截止到python版本3.6.2,现在python一共为 ...
- linux shell 之尝试编写 企业级 启动脚本
企业Shell面试题10:开发企业级MySQL启动脚本 说明: MySQL启动命令为: 1 /bin/sh mysqld_safe --pid-file=$mysqld_pid_file_path 2 ...
- SSH远程联机Linux服务器简易安全设定
分别可以由底下这三方面来进行: 1.服务器软件本身的设定强化:/etc/ssh/sshd_config 2.TCP wrapper 的使用:/etc/hosts.allow, /etc/hosts.d ...
- 002_运维SOP
一. <1>SOP:运维工作的标准化 <2>回滚:代码回滚 <3>降级:是利用有限资源,保障系统核心功能高可用.有损的架构方法 <4>多活切换:多机房切 ...
- mysql5.7 pxc
pxc优点总结:可以达到时时同步,无延迟现象发生完全兼容MySQL对于集群中新节点的加入,维护起来很简单数据的强一致性不足之处总结:只支持Innodb存储引擎存在多节点update更新问题,也就是写放 ...