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 ...
随机推荐
- 【mmall】mybatis三剑客
mybatis-generator mybatis-plugin Mybatis Plugin插件安装破解及使用:http://blog.csdn.net/u011410529/article/det ...
- AspectJ使用的遇到的坑
1.导入包,但不是使用,会导致R文件错误 apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply pl ...
- P2709 小B的询问(莫队入门)
题目链接:https://www.luogu.org/problemnew/show/P2709 题目大意:中文题目 具体思路:莫队入门题,按照离线的方式打的,对每一个区间进行分块和编号,如果在同一个 ...
- java汇总
BeanUtils 操作Javabean 需要导入jar包,并且加入到构建路径里面去,选择右键--加入到****,jar包的图标变成奶瓶: => 位置会变成上一层: ======== 原来已经配 ...
- Setup Post-mission Camera
编辑BP_GameMode 新建Actor命名为BP_SpectatingViewpoint 添加摄像机 将摄像机调整到合适的位置,右键选择 调整到合适的位置,点击这个按钮,退出驾驶模式 摄像机已经移 ...
- 【转】gcc命令中参数c和o混合使用的详解
gcc -c a.c 编译成目标文件a.o gcc a.c 生成执行文件a.exe gcc -o a -c a.c 编译成目标文件a gcc -o a a.c 生成执行文件a. ...
- window.opener和window.open的使用
window.opener和window.open的使用 window.opener是指调用window.open方法的窗口.window.opener 返回的是创建当前窗口的那个窗口的引用,比如点击 ...
- web@HTML重要标签详介绍.
1.table标签<table border="1px " rules="groups" cellpadding="5px" cell ...
- MySQL--(了解)可能会用到的内置函数
mysql内置函数列表可以从mysql官方文档查询,这里仅分类简单介绍一些可能会用到的函数.1 数学函数abs(x)pi()mod(x,y)sqrt(x)ceil(x)或者ceiling(x)rand ...
- mysql 命令行常用命令
1.显示数据库列表. show databases; 2.显示库中的数据表: use mysql; show tables; 3.显示数据表的结构: describe 表名; 4.建库: cr ...