BZOJ 4011 HNOI2015 落憶楓音

2022-06-01 09:27:11 字數 1954 閱讀 2275

ac通道:

題目很長,寫得也很有詩意與浪漫色彩,讓我們不禁感嘆出題人是乙個多麼英俊瀟灑的人。

所以題目大意就是:

給乙個有向無環圖,問加上一條我給定的邊後,有多少個以1為根的樹形圖?n<=1e5,m<=2*1e5

原圖無重邊,加上的邊可以為自環。

首先先來解決乙個問題:

乙個有向無環圖的樹形圖有多少個呢? 

相當於除了根節點以外,每個點隨意取乙個入度,為什麼就一棵樹呢?每個點選乙個父親,並且保證沒有環,所以是一棵樹。

好的,對於有向無環圖就一定是這樣的,那麼若加入一條邊,

那麼就可能再選擇的過程中選出乙個環[就是祖先的父親是自己這種情況]。那麼我們就需要刪去這種情況。

首先要出現環,則必定包括了這條邊,剩下的部分是原圖中y->x的一條路徑,要求這條路徑上的點必須選擇一條路徑使得構成乙個環。而其它的點可以隨意選。

設f(i)表示y->i上的點所成路徑必須選擇一條能構成環路徑的方案數。

有初始值:

遞推式:

相當於j可以選擇延續所有從y走來的i的路徑,但是要除以j原本可以選擇的路徑總數。

最後答案=所有方案[入度乘積] - f(x)。

聽說zzd去年就想出來了這題,不過因為不會打逆元而失之交臂[不然就是省隊了?%%%]

為什麼會有逆元?...額我好像忘記說方案數要取模了...

那麼這題中為了加速運算,就用了乙個o(n)遞推求1...n的所有逆元的方法,我也算是普及一下吧?...

畫圖的時候沒太注意大小寫,不要太在意...

那麼i的逆元可以由p mod i的逆元得知了,這顯然是乙個已知的數,所以每次遞推都是o(1)的,邊界:1的逆元=1。

#include#include

#include

using

namespace

std;

inline

intin

()const

int maxn=100010

;const

int mod=1e9+7

;typedef

long

long

ll;struct

nodenode[maxn

<<1

];#define now node[point].data

#define then node[point].next

intn,m,ans,cnt,x,y;

inthead[maxn],d[maxn],ld[maxn];

intf[maxn],stack[maxn],top;

int inv[maxn<<1

];void

init()

void add(int u,int

v)int power(int a,int

k)

return

ans;

}int

main()

else f[y]=(ll)ans*inv[d[y]]%mod;

d[y]--;

memcpy(ld,d,

sizeof

(d));

for(int i=1;i<=n;i++) if(!d[i]) stack[++top]=i;

while

(top)

}ans=(ans-f[x]+mod)%mod;

printf("%d

",ans);

return0;

}

view code

BZOJ 4011 HNOI2015 落憶楓音

題意 給乙個有向無環圖,然後叫一條邊,問以1為根的生成樹數量。題面好長啊,出題人真能編故事 先考慮不加那條邊,則麼ans d 2 d 3 d 4 d n d為入度 因為在乙個dag中,只要除根以外的點每個點選一條入邊,就能獲得一棵生成樹。現在考慮加了這條邊,如果再這麼算,就有可能出現環的情況,所以我...

BZOJ4011 HNOI2015 落憶楓音

用脈絡樹總數減去不合法的情況 即樹上有環的情況 拓撲序dp,注意特判連的邊指向1的情況 學到了新姿勢 線性求逆元 原理 假設現在要求a的逆元,x mod a,y mod a ax y 0 ax y a 1 x y 1 ax y 0 ax y a 1 x y 1 code include includ...

BZOJ4011 HNOI2015 落憶楓音

不妨假設楓葉上有 n個穴位,穴位的編號為 1 n。有若干條有向的脈絡連線著這些穴位。穴位和脈絡組成乙個有向無環圖 稱之為脈絡圖 例如圖 1 穴位的編號使得穴位 1 沒有從其他穴位連向它的脈絡,即穴位 1 只有連出去的脈絡 由上面的故事可知,這個有向無環圖存在乙個樹形子圖,它是以穴位 1為根的包含全部...