洛谷 P3244 / loj 2115 [HNOI2015] 落忆枫音 题解【拓扑排序】【组合】【逆元】

组合计数的一道好题。什么非主流题目

题目背景

(背景冗长请到题目页面查看)

题目描述

不妨假设枫叶上有 \(n​\) 个穴位,穴位的编号为 \(1\sim n​\)。有若干条有向的脉络连接着这些穴位。穴位和脉络组成一个有向无环图——称之为脉络图(例如图 1),穴位的编号使得穴位 \(1​\) 没有从其他穴位连向它的脉络,即穴位 1 只有连出去的脉络;由上面的故事可知,这个有向无环图存在一个树形子图,它是以穴位 \(1​\) 为根的包含全部 \(n​\) 个穴位的一棵树——称之为脉络树(例如图 2 和图 3 给出的树都是图 1 给出的脉络图的子图);值得注意的是,脉络图中的脉络树方案可能有多种可能性,例如图 2 和图 3 就是图 1 给出的脉络图的两个脉络树方案。

5c6cfe1e60786.png

脉络树的形式化定义为:以穴位 \(r\) 为根的脉络树由枫叶上全部 \(n\) 个穴位以及 \(n-1\) 条脉络组成,脉络树里没有环,亦不存在从一个穴位连向自身的脉络,且对于枫叶上的每个穴位 \(s\),都存在一条唯一的包含于脉络树内的脉络路径,使得从穴位 \(r\) 出发沿着这条路径可以到达穴位 \(s\)

现在向脉络图添加一条与已有脉络不同的脉络(注意:连接 \(2\) 个穴位但方向不同的脉络是不同的脉络,例如从穴位 \(3\)\(4\) 的脉络与从 \(4\)\(3\) 的脉络是不同的脉络,因此,图 1 中不能添加从 \(3\)\(4\) 的脉络,但可添加从 \(4\)\(3\) 的脉络),这条新脉络可以是从一个穴位连向自身的(例如,图 1 中可添加从 \(4\)\(4\) 的脉络)。原脉络图添加这条新脉络后得到的新脉络图可能会出现脉络构成的环。

请你求出添加了这一条脉络之后的新脉络图的以穴位 \(1\) 为根的脉络树方案数。

由于方案可能有太多太多,请输出方案数对 \(1000000007\) 取模得到的结果。

输入格式

输入文件的第一行包含四个整数 \(n\)\(m\)\(x\)\(y\),依次代表枫叶上的穴位数、脉络数,以及要添加的脉络是从穴位 \(x\) 连向穴位 \(y\) 的。

接下来 \(m\) 行,每行两个整数,由空格隔开,代表一条脉络。第 \(i\) 行的两个整数为 \(u_i\)\(v_i\),代表第 \(i\) 条脉络是从穴位 \(u_i\) 连向穴位 \(v_i\) 的。

输出格式

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

输入输出样例

输入样例:

4 4 4 3 
1 2 
1 3 
2 4 
3 2

输出样例:

3

数据范围与约定

对于所有测试数据,\(1\leq n\leq 100000, \ n-1 \leq m \leq \min \left(200000, \frac{n(n - 1)}{2}\right), \ 1 \leq x, y, u_i, v_i \leq n​\)

题解:

首先需要找出一个不需要拓扑排序就能解决不加边时的脉络树数量的方法。

对于每个点 \(u(u\ge 2)\) ,假定它的入度为 \(d_i\) ,则它有 \(d_i\) 个父亲可供选择。我们只需要从上往下看,就可以发现每一层都是互相独立的,因此加边之前脉络树的数量为
\[ \prod_{i=2}^nd_i \]
此时考虑加边。正常情况下按上面的方式计数,边数为 \(n-1\) 的图的总数 \(sum\)
\[ sum=\prod_{i=2}^n\left(d_i+[i=y]\right) \]
但是实际上不是所有 \(sum\) 种方案都符合题意,由于每个点选择父亲是自由从入边选的,因此可能存在环,此时就不满足”脉络树“的定义了,而且图/树也没有明显分层。

我们考虑所有的 \(sum​\) 种方案,从中减掉包含环的那些方案。由于我们加入的边是 \(\left<x,y\right>​\),所以一定是与路径 \(y\to x​\) 成环。因此我们只需要排除那些包含 \(y\to x\) 的路径的边数为 \(n-1​\) 的图就可以了。

注意由于加了新边之后的图只有一个环,因此 \(n-1​\) 条边的图也最多只有一个环。

话再说回来,包含 \(y\to x​\) 的路径的图我们可以认为这条路径上的所有点(包括 \(x,y​\))都被钦定了一个父亲(其中 \(x​\) 的父亲认为是 \(y​\),因为要成环)。假设用 \(S=\left\{a_i\right\}​\) 表示这条路径,那么包含 \(y\to x​\) 的图种类数就是 \(\prod_{i\notin S}d_i​\)

而最终的答案就是 \(sum-\sum_{S:y\to x}\prod_{i\notin S}d_i​\)

此时考虑如何求出所有的 \(y\to x\)。可以建立原图的反向边,跑拓扑排序。设定状态 \(f_k\) 表示 \(\sum_{S:k\to x}\prod_{i\notin S}d_i\),每次从原图的边 \(\left<u,v\right>\) 转移时,即钦定了 \(v\) 的入边,所以状态转移方程为
\[ f_u=\sum_{\left<u,v\right>\in E}\frac{f_v}{d_v} \]
由于我们还要钦定 \(x\) 的入边是 \(y\),因此最终的答案是
\[ ans=sum-\frac{f_x}{d_x} \]
时间复杂度为 \(O(n)\)\(O(n\log n)\) (在线求逆元)

Code:

#include<cstdio>
#include<cstring>
#define p 1000000007
int Plus(int x,int y)
{return (x+y>=p)?(x+y-p):(x+y);}
int Mul(int x,int y)
{return 1ll*x*y%p;}
struct edge
{int n,nxt;edge(int n,int nxt){this->n=n;this->nxt=nxt;}edge(){}
}e[200000];
int head[100100],ecnt=-1;
void add(int from,int to)
{e[++ecnt]=edge(to,head[from]);head[from]=ecnt;
}
int d[100100],in[100100];
//d表示真实入度 in表示拓扑排序中的入度
int q[100100],l=0,r=0;
int f[100100],inv[100100];
int main()
{memset(head,-1,sizeof(head));inv[1]=1;for(int i=2;i<=100000;++i)inv[i]=Mul(p-p/i,inv[p%i]);int n,m,x,y,u,v;scanf("%d%d%d%d",&n,&m,&x,&y);for(int i=1;i<=m;++i){scanf("%d%d",&u,&v);add(v,u);++in[u];++d[v];}f[x]=1;int sum=1;for(int i=2;i<=n;++i){if(!in[i])q[++r]=i;f[x]=Mul(f[x],d[i]);sum=Mul(sum,d[i]+(i==y));}if(y==1){printf("%d\n",sum);return 0;}while(l<r){int k=q[++l];for(int i=head[k];~i;i=e[i].nxt){--in[e[i].n];f[e[i].n]=Plus(f[e[i].n],Mul(f[k],inv[d[k]]));if(!in[e[i].n])q[++r]=e[i].n;}}printf("%d\n",Plus(sum,p-Mul(f[y],inv[d[y]])));return 0;
}

转载于:https://www.cnblogs.com/wjyyy/p/lg3244.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/412100.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[vue] 说说你对选项el,template,render的理解

[vue] 说说你对选项el,template,render的理解 el: 把当前实例挂载在元素上 template: 实例模版, 可以是.vue中的template, 也可以是template选项, 最终会编译成render函数 render: 不需要通过编译的可执行函数template和render, 开发时各有优缺点, 不过在线上尽量不要有templa…

mysql获取离当前数据最近的数据_Mysql 获取最近数据信息

今天select * from 表名 where to_days(时间字段名) to_days(now());昨天SELECT * FROM 表名 WHERE TO_DAYS( NOW( ) ) – TO_DAYS( 时间字段名) < 1近7天SELECT * FROM 表名 where DATE_SUB(CURDATE(), INTERVAL 7 DAY) < date(时间字段名)近30天SELECT * FROM 表名 wh…

参加宴会的烦恼

公司历经很多磨难&#xff0c;终于挺过来了&#xff0c;明天就是正式重新成立的日子&#xff0c;我有幸去参加宴会&#xff0c;要求穿便服&#xff0c;一年四季穿工作服习惯了&#xff0c;自己衣服倒不知道该怎么穿了。看来我又要败家了。。。。。看中的衣服都好贵&#xff0c;…

[vue] 说说你使用vue过程中遇到的问题(坑)有哪些,你是怎么解决的?

[vue] 说说你使用vue过程中遇到的问题&#xff08;坑&#xff09;有哪些&#xff0c;你是怎么解决的&#xff1f; 从详情页返回列表页时, 要保存所有状态, 比如: 滚动条位置, 数据, 下拉数据等 当时想用keep-alive, 后来没用, 直接存储一些关键数据, 返回到router时重新加载了…

python 列表嵌套字典 添加修改删除_【Python】列表嵌套字典修改字典里面的一个值却把全部的值都修改了。...

具体问题就是&#xff1a;当我往空列表里面添加字典&#xff0c;需要修改其中的一个键的值的时候&#xff0c;出现把其他同类的值也修改了。下面就是出现问题的代码&#xff1a;aliens []new_alien {"color": "green"}#往字典里添加5个字典for num in ra…

配置msf连接postgresql数据库

BackTrack 5 R3版本的Metasploit在每次的升级后总会出现奇奇怪怪的错误&#xff0c;主要是Ruby的库出错&#xff0c;网上找了一些解决的办法&#xff0c;但每次更新后又会出错&#xff0c;蛋碎。 解决方法&#xff1a; BackTrack 5中默认自动开启端口7337。 1、查看PostgreSQL端…

js :check 檢查

DropDownList是否選定的判定&#xff1a;if (Form1.DropDownList1.selectedIndex(parseInt("0"))){ alert("12555"); return false;}checkbox是否選定的判定&#xff1a;if (document.Form1.RadioButton1.checkedfalse) { alert(請選定復判結果&#x…

[vue] 组件和插件有什么区别?

[vue] 组件和插件有什么区别&#xff1f; 组件 (Component) 是用来构成你的 App 的业务模块&#xff0c;它的目标是 App.vue。插件 (Plugin) 是用来增强你的技术栈的功能模块&#xff0c;它的目标是 Vue 本身。个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放…

java8 stream to map_Java 8 Stream Api 中的 map和 flatMap 操作

1.前言Java 8 提供了非常好用的 Stream API ,可以很方便的操作集合。今天我们来探讨两个 Stream 中间操作 map 和 flatMap2. map 操作map 操作是将流中的元素进行再次加工形成一个新流。这在开发中很有用。比如我们有一个学生集合&#xff0c;我们需要从中提取学生的年龄以分析…

string和byte[]的相互转换

string --> byte[]byte[] dataSyste.Text.Encoding.ASCII.GetBytes(string);byte[]-->stringstring string1 Encoding.ASCII.GetString( bytes, 0, bytesSize );如果有中文字符把Encoding.ASCII换成Encoding.GetEncoding("gb2312") 转载于:https://www.cnblogs…

imagemagick for java_ImageMagick使用for java(im4java)

简介&#xff1a;用于读、写、处理图片文件&#xff0c;支持89种格式的图片文件&#xff0c;利用imageMagick可以根据web应用程序动态生成图片&#xff0c;也可以将一个或者一组图片改变大小、旋转、锐化、减色、增加特效等操作&#xff0c;并对操作结果进行保存(可以设置保存格…

[收藏]网络营销十道羊皮卷

羊皮卷之一&#xff1a;一个与企业名称和形象相符的域名&#xff0c;是企业进行网络营销的前提。由于域名具有唯一性&#xff0c;一个域名一旦注册成功&#xff0c;任何其他机构都无法注册相同的域名。因此&#xff0c;域名是企业重要的网络商标&#xff0c;在网络营销中起到企…

[vue] 删除数组用delete和Vue.delete有什么区别?

[vue] 删除数组用delete和Vue.delete有什么区别&#xff1f; delete&#xff1a;只是被删除数组成员变为 empty / undefined&#xff0c;其他元素键值不变Vue.delete&#xff1a;直接删了数组成员&#xff0c;并改变了数组的键值&#xff08;对象是响应式的&#xff0c;确保删除…

Python模块学习

阅读目录 第一篇&#xff1a;Python模块之netmiko 第二篇&#xff1a;Python模块之junos-eznc 第三篇&#xff1a;Python模块之pexpect 第四篇&#xff1a;Python模块之paramiko 第五篇&#xff1a;Python模块之XlsxWriter 第六篇&#xff1a;Python模块之requests,urllib和re …

web文件加密

讲解以及源代码下载ASP.NET 2.0: Encrypting Connection Strings http://blogs.vertigosoftware.com/snyholm/archive/2005/12/16/1746.aspx http://msdn2.microsoft.com/en-us/library/yxw286t2.aspx中文http://msdn2.microsoft.com/zh-cn/library/yxw286t2.aspx ASP.NET 2.0:…

java开发和android开发_浅谈Java开发和Android开发的不同

Java是具有多种用例的完整开发语言&#xff0c;包括Web开发&#xff0c;PC程序开发&#xff0c;嵌入式开发等。Android开发是面向手机应用&#xff0c;使用Java较多&#xff0c;还有常用的H5跨平台混合架构模式。一&#xff0c;UI界面开发不同1)Java Swing现在Java开发基本上都…

[vue] v-model是什么?有什么用呢?

[vue] v-model是什么&#xff1f;有什么用呢&#xff1f; 一则语法糖&#xff0c;相当于v-bind:value"xxx" 和 input&#xff0c;意思是绑定了一个value属性的值&#xff0c;子组件可对value属性监听&#xff0c;通过$emit(input, xxx)的方式给父组件通讯。自己实现…

远程上传下载文件-Xftp5

Xftp5下载 链接&#xff1a;https://pan.baidu.com/s/1Wzso_Q7mPy5uGOUlripEWg 密码&#xff1a;xfx9 安装选择家庭版 由于21端口没有开&#xff0c;所以不能选FTP, 选择SFTP&#xff0c;22端口 用哪个用户登录机会自动到该用户的家目录 连接上出先乱码问题 属性 OK. 转载于:h…

java反射 pdf_java反射学习笔记整理.pdf

java反射学习笔记整理.pdf还剩15页未读&#xff0c;继续阅读下载文档到电脑&#xff0c;马上远离加班熬夜&#xff01;亲&#xff0c;很抱歉&#xff0c;此页已超出免费预览范围啦&#xff01;如果喜欢就下载吧&#xff0c;价低环保&#xff01;内容要点&#xff1a;Java 反射笔…

变态跳台阶

题目描述 一只青蛙一次可以跳上1级台阶&#xff0c;也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。题解 简要提炼思路&#xff1a; 1、有n个台阶&#xff0c;则每次可以跳1&#xff0c;2&#xff0c;3&#xff0c;&#xff0c;&#xff0c;n个…