落憶楓音(BZOJ 4011 HNOI2015)
阿新 • • 發佈:2018-12-19
Analysis
莫名其妙地被題面虐了一把
很好的一道結論題(?)
由朱劉演算法的推論可知,如果除根節點外每個點都選擇一條入邊,由於沒有環,因此一定會形成一個樹形圖 答案就是 其中degree[i]表示第i個點的入度 但是現在我們加入了一條邊,圖中就可能形成環 我們需要做的就是,依然用上述式子算答案,再減去不合法的環的情況 不合法 環的情況,就是
翻譯為人話,就是說:現在強制選擇環,然後其他的點隨便選的不合法方案數 那麼我們的目標就是求出上面那個式子,怎麼求呢? 可以考慮dp,狀態轉移
(是可以到達的點)
Code
#include<bits/stdc++.h>
#define in read()
#define N 100009
#define M 200010
#define P 1000000007
using namespace std;
inline int read(){
char ch;int f=1,res=0;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
while(ch>='0'&&ch<='9'){res=(res<<3)+(res<<1)+ch-'0';ch=getchar();}
return f==1?res:-res;
}
int n,m,x,y,ans=1;
int f[N],inv[M];
int deg[N],__deg[N];
int nxt[M] ,to[M],head[N],ecnt=0;
inline void add(int x,int y){nxt[++ecnt]=head[x];head[x]=ecnt;to[ecnt]=y;}
inline int mul(int a,int b){return a*1ll*b%P;}
inline void topsort(){
queue<int> q;
for(int i=1;i<=n;++i)
if(!deg[i]) q.push(i);
while(!q.empty()){
int u=q.front();q.pop();
f[u]=(f[u]*1ll*inv[__deg[u]])%P;
for(int e=head[u];e;e=nxt[e]){
int v=to[e];
f[v]=(f[u]+f[v])%P;
--deg[v];
if(!deg[v]) q.push(v);
}
}
}
inline void init(){
inv[1]=1;
for(int i=2;i<=m+1;++i)
inv[i]=(P-P/i)*1ll*inv[P%i]%P;
}
int main(){
n=in;m=in;x=in;y=in;
__deg[y]++;
init();
int i,j,k,u,v;
for(i=1;i<=m;++i){
u=in;v=in;
add(u,v);deg[v]++;__deg[v]++;
}
for(i=2;i<=n;++i) ans=mul(ans,__deg[i]);
if(y==1){
printf("%d",ans);
return 0;
}
f[y]=ans;
topsort();
printf("%d",(ans-f[x]+P)%P);
return 0;
}