2018.07.13 [HNOI2015]落忆枫音(容斥原理+dp)
2024-08-28 04:40:33
洛谷的传送门
bzoj的传送门
题意简述:在DAG中增加一条有向边,然后询问新图中一共 有多少个不同的子图为“树形图”。
解法:容斥原理+dp,先考虑没有环的情况,经过尝试不难发现总的有向树个数就等于所有点的度数的乘积。而现在有了环,显然我们应该减去算多了的值。这样的话只需要简单的容斥原理就行了。
代码如下:
#include<bits/stdc++.h>
#define mod 1000000007
#define N 200005
#define M 400005
#define ll long long
using namespace std;
inline ll read(){
ll ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
return ans;
}
ll n,m,x,y,tot=0,first[N];
ll ans=1,mul=1,dp[N],du[N];
bool vis[N];
struct Node{ll v,next;}e[M];
inline void add(ll u,ll v){e[++tot].v=v,e[tot].next=first[u],first[u]=tot,++du[u];}
inline ll ksm(ll x,ll p){
ll ret=1;
while(p){
if(p&1)ret=ret*x%mod;
x=x*x%mod,p>>=1;
}
return ret;
}
inline void dfs(ll p){
if(vis[p])return;
vis[p]=true;
if(p==y){dp[p]=mul*ksm(du[p],mod-2)%mod;return;}
for(ll i=first[p];i;i=e[i].next){
dfs(e[i].v),dp[p]+=dp[e[i].v],dp[p]%=mod;
}
dp[p]=(dp[p]*ksm(du[p],mod-2))%mod;
}
int main(){
memset(vis,false,sizeof(vis));
n=read(),m=read(),x=read(),y=read();
for(ll i=1;i<=m;++i){ll u=read(),v=read();add(v,u);}
du[1]=1;
for(ll i=1;i<=n;++i){
if(i==y)ans*=(du[i]+1),ans%=mod;
else ans*=du[i],ans%=mod;
mul*=du[i],mul%=mod;
}
dfs(x);
ans-=dp[x];
if(ans<0)ans+=mod;
printf("%lld",ans);
return 0;
}
最新文章
- Qt之C语言类型typedef a[]等
- 多个 git ssh key 配置 Ubuntu os
- Linq表达式开窍
- Note | Javascript权威指南[第六版] 第1章:Javascript概述
- Fedora Linux 下安装配置C开发环境Code::Blocks
- 在 树莓派上使用 c++ libsockets library
- 执行查询&ldquo;BACKUP LOG [XXX] TO DISK = N'F:\\BackData\\事务日至备份\\...&rdquo;失败,错误如下:&ldquo;无法执行 BACKUP LOG,因为当前没有数据库备份。 BACKUP LOG 正在异常终止。
- YARN的三种调度器的使用
- html 佈局
- 10.0-uC/OS-III任务管理
- 改变端口的方法phpstudy
- BOM 对象--location、navigator、screen、history
- Python中的类方法、实例方法、静态方法
- Leetcode[1]Two Sum C++
- angular2+ 初理解
- git使用总结(常用命令)
- 设计一个分布式RPC框架
- 【LeetCode】132. Palindrome Partitioning II
- mysql 分数表实现排名
- 最小可用 Spring MVC 配置