[HNOI 2015]落忆枫音
Description
「恒逸,你相信灵魂的存在吗?」
Input
输入文件的第一行包含四个整数 n、m、x和y,依次代表枫叶上的穴位数、脉
Output
输出一行,为添加了从穴位 x连向穴位 y的脉络后,枫叶上以穴位 1 为根的脉
Sample Input
1 2
1 3
2 4
3 2
Sample Output
HINT
对于所有测试数据,1 <= n <= 100000,n - 1 <= m <= min(200000, n(n – 1) / 2),
题解
首先我们简化这个问题,考虑一个$DAG$中树形图的个数。
值得注意的是这里有朱刘算法的一个推广:
如果除根节点外每个点都选择一条入边,由于没有环,因此一定会形成一个树形图。
这里简要证明一下:
首先证明这个图是联通的。
采用反证法,假设图不联通,显然原图存在一个子图满足:子图联通,并且子图中边数$w$>点数$u$。
那么这样这个子图的总入度>总点数。那么一定存在一个点入度>$1$。与题设不符,原命题成立。
下证这个连通图满足树形图的性质。
依旧采用反证法,我们假设选择满足题意的边不能够成树形图。那么存在两条不同的路径$S_1$,$S_2$从根节点$1$到达另外一个节点$v$。
假设子图$g(u',w') ⊂$ 原图$G(u,w)$是满足$S_1,S_2 ⊂ g(u',w')$的极小子图。
既然存在两条不同的路径,显然$u' <= w'$。
又由于除根节点外每个点有且仅有一个入边,显然$w' = u'-1$。矛盾,原命题成立。
由上述结论,显然简化版的问题答案就是:$$ans = \prod_{i=2}^n degree_i(其中degree_i表示节点i的入度)$$
我们再来考虑原问题,现在加上额外的一条边之后,原图可能形成环。再由上面的决策,显然不可行。
我们考虑不合法的情况是什么:显然选边的时候构成环就是不合法的。并且这个环中的一条边肯定是$x \rightarrow y$。
容易得到的结论就是,需要减去的不合法的值就是$$\sum_{S是G中y \rightarrow x的一条路径的点集}\prod_{2\leq j\leq n,j\notin S}degree_j$$
考虑贡献法来计算,用$top-sort-dp$,记$f_i$表示$$\sum_{S是G中y \rightarrow i的一条路径的点集}\prod_{2\leq j\leq n,j\notin S}degree_j$$
$dp$方程就是$$f_i=\frac{\sum_{j\rightarrow i}f_j}{degree_i}$$
初值$$f_y=\frac{\prod_{i=2}^ndegree_i}{degree_y}$$
由于$1$号根节点不选入边,所以$1$号点显然不能构成环。若$y == 1$,显然这条边不可能被选,不用$top-sort-dp$,直接输出原始$ans$即可。
//It is made by Awson on 2017.12.24
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
using namespace std;
const int N = ;
const int M = ;
const int MOD = ; int n, m, x, y, u, v;
struct tt {
int to, next;
}edge[M+];
int path[N+], top;
int ans = , degree[N+], in[N+];
int f[N+];
queue<int>Q; int quick_pow(int a, int b) {
int cnt = ;
while (b) {
if (b&) cnt = (LL)cnt*a%MOD;
a = (LL)a*a%MOD;
b >>= ;
}
return cnt;
}
void topsort() {
f[y] = ans;
for (int i = ; i <= n; i++) if (in[i] == ) Q.push(i);
while (!Q.empty()) {
int u = Q.front(); Q.pop();
f[u] = (LL)f[u]*quick_pow(degree[u], MOD-)%MOD;
for (int i = path[u]; i; i = edge[i].next) {
(f[edge[i].to] += f[u]) %= MOD; in[edge[i].to]--;
if (in[edge[i].to] == ) Q.push(edge[i].to);
}
}
}
void add(int u, int v) {
edge[++top].to = v;
edge[top].next = path[u];
path[u] = top;
}
void work() {
scanf("%d%d%d%d", &n, &m, &x, &y);
degree[y]++;
for (int i = ; i <= m; i++) {
scanf("%d%d", &u, &v);
add(u, v); degree[v]++;
}
for (int i = ; i <= n; i++) ans = (LL)ans*degree[i]%MOD;
for (int i = ; i <= n; i++) in[i] = degree[i]; in[y]--;
if (y != ) topsort();
printf("%d\n", (ans-f[x]+MOD)%MOD);
}
int main() {
work();
return ;
}
[HNOI 2015]落忆枫音的更多相关文章
- 【BZOJ】【4011】【HNOI2015】落忆枫音
拓扑排序+DP 题解:http://blog.csdn.net/PoPoQQQ/article/details/45194103 http://www.cnblogs.com/mmlz/p/44487 ...
- BZOJ 4011: [HNOI2015]落忆枫音( dp )
DAG上有个环, 先按DAG计数(所有节点入度的乘积), 然后再减去按拓扑序dp求出的不合法方案数(形成环的方案数). ---------------------------------------- ...
- bzoj4011[HNOI2015]落忆枫音 dp+容斥(?)
4011: [HNOI2015]落忆枫音 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1125 Solved: 603[Submit][Statu ...
- [HNOI2015]落忆枫音 解题报告
[HNOI2015]落忆枫音 设每个点入度是\(d_i\),如果不加边,答案是 \[ \prod_{i=2}^nd_i \] 意思是我们给每个点选一个父亲 然后我们加了一条边,最后如果还这么统计,那么 ...
- 4011: [HNOI2015]落忆枫音
4011: [HNOI2015]落忆枫音 链接 分析: 原来是一个DAG,考虑如何构造树形图,显然可以给每个点找一个父节点,所以树形图的个数就是$\prod\limits_u deg[u]$. 那么加 ...
- BZOJ 4011 【HNOI2015】 落忆枫音
题目链接:落忆枫音 以下内容参考PoPoQQQ大爷的博客 首先我们先来考虑一下如果没有新加入的那条边,答案怎么算. 由于这是一个\(DAG\),所以我们给每个点随便选择一条入边,最后一定会构成一个树形 ...
- 【BZOJ4011】【HNOI2015】落忆枫音(动态规划)
[BZOJ4011][HNOI2015]落忆枫音(动态规划) 题面 BZOJ 洛谷 Description 「恒逸,你相信灵魂的存在吗?」 郭恒逸和姚枫茜漫步在枫音乡的街道上.望着漫天飞舞的红枫,枫茜 ...
- BZOJ4011: [HNOI2015]落忆枫音
Description 「恒逸,你相信灵魂的存在吗?」 郭恒逸和姚枫茜漫步在枫音乡的街道上.望着漫天飞舞的红枫,枫茜突然问出 这样一个问题. 「相信吧.不然我们是什么,一团肉吗?要不是有灵魂……我们 ...
- [HNOI2015]落忆枫音
题目描述 「恒逸,你相信灵魂的存在吗?」 郭恒逸和姚枫茜漫步在枫音乡的街道上.望着漫天飞舞的红枫,枫茜突然问出这样一个问题. 「相信吧.不然我们是什么,一团肉吗?要不是有灵魂......我们也不可能再 ...
随机推荐
- java中的异常以及 try catch finally以及finally的执行顺序
java中的 try.catch.finally及finally执行顺序详解: 1.首相简单介绍一下异常以及异常的运行情况: 在Java中异常的继承主要有两个: Error和Exception 这两个 ...
- 听翁恺老师mooc笔记(4)--指针的应用场景
指针应用场景一:交换两个变量的值 在学习函数时,交换两个数的值,做一个swap函数,传递值进去,也可以将两个值交换过来,没问题,可是离开swap就没有用了,为什么?因为传进去的是两个值. #inclu ...
- 数据结构——线性表——队列(queue)
队列也是一种特殊的线性表,它的特点是先入先出(FIFO,即first in first out).它的意思也很直观,想象一下排队买票,先排的人先买(插队是不对的,所以别去想).它也是很常用的数据结构, ...
- 团队作业7——第二次项目冲刺(Beta版本12.04)
1.当天站立式会议照片 本次会议内容:1:每个人汇报自己完成的工作.2:组长分配各自要完成的任务. 2.每个人的工作 黄进勇:项目整合,后台代码. 李勇:前台界面优化. 何忠鹏:数据库模块. 郑希彬: ...
- SQL的介绍及MySQL的安装
基础篇 - SQL 介绍及 MySQL 安装 SQL的介绍及MySQL的安装 课程介绍 本课程为实验楼提供的 MySQL 实验教程,所有的步骤都在实验楼在线实验环境中完成, ...
- 201621123027 《Java程序设计》第1周学习总结
01621123027 <Java程序设计>第1周学习总结 1.本周学习总结 关键词:总概.承接.面向对象化 我认为第一周的Java学习是一些总结概括性质的内容,在比较联系之前学习过的 ...
- vue jquery js 获取当前时间本周的第一天 和 本月的第一天
交互的时候传输数据 后台要求这样的数据 直接上代码 这是我找度姨要的 附上链接 https://www.cnblogs.com/wasabii/p/7756560.html 它里面有本季度第一天 ...
- Python-socket网络编程-Day8
目录Day8-Python socket 11.Socket 11.1.socket和file的区别: 11.2.WEB服务应用: 21.3.更多功能 21.4.socket方法: 41.5. 服务端 ...
- XML之XPath
1.在 XPath 中,有七种类型的节点:元素.属性.文本.命名空间.处理指令.注释以及文档节点(或称为根节点). 1.1 XPath 术语 节点(Node) 在 XPath 中,有七种类型的节点:元 ...
- 访问器属性:setter()函数和getter()函数
1.干嘛用的? getter()函数:返回有效的值 setter()函数:调用它并传入数据,这个函数决定如何处理数据 2.具备哪些属性?如何定义? configurable(默认为true),enum ...