description
input
output
sample input
輸入1:sample output4 4 4 3
1 21 3
2 43 2
輸入2:
10 16 7 2
1 21 8
2 32 4
3 53 6
4 54 6
5 76 7
7 10
8 48 6
8 99 6
9 10
輸出1:3
輸出2:data constraint92
首先有乙個重要結論!
對於乙個有向無環圖(dag),它的生成樹個數就等於除根外所有點入度的乘積!
我考試的時候不知道這玩意然後直接gg了。。。
然後我們加入了一條邊,可能會形成環,有環仍按以上方法計算會有不合法的情況,那麼我們用總方案減去不合法的方案即是ans
不合法方案的環中一定會包含我們新加入的邊x->y
那麼假設環中剩餘的路徑y->x,那麼形成這樣的環的方案數即為,總數/(在路徑上的點的入度積),因為在路徑上的點入度只能選路徑上的邊,其他的點仍可以隨便選,
除法用逆元處理,那麼我們設g[i]為所有y到i路徑上的點的逆元的路的總和,按拓撲序dp一遍求出g[x]即可
#include#include#include
#include
#include
using
namespace
std;
typedef
long
long
ll;int mo=1000000007
;int du[100011],fc[100011],g[100011],next[200011],y[200011],que[200011
];int
l,r,x,j,k,n,m,tx,ty,z,i,ans,tt,la;
int f[100011
];void star(int i,int
j)int mi(int x,int
z)
returnl;}
intmain()
if(tx==ty||ty==1
)
else
l=r=1
; que[l]=1
;
while(l<=r)
j=next[j];
}l++;
}f[ty]=fc[ty];
l=r=1
; que[l]=ty;
while(l<=r)
j=next[j];
}l++;
}la=(ll)la*f[tx]%mo;
ans=ans-la;
ans=(ans%mo+mo)%mo;
printf(
"%d\n
",ans);}}
HNOI2015 落憶楓音
hnoi2015 落憶楓音 首先 原圖是乙個dag 生成樹即為除了根節點以外每個節點隨便選一條入邊組成的 所以生成樹數量 各個點入度乘積 新加入一條邊 分三種情況 1.如果不成環 那麼可以把它放在原來的dag裡計算 2.如果它的終點為1 那麼忽略不計 3.如果它成環的話 假設其中乙個環大小是size...
HNOI2015 落憶楓音
嘟嘟嘟 這題大意就是有乙個dag,然後新增了一條邊,求上有多少種生成樹。這題想了半天,最後還是寫了暴力。暴力就是 o 2 mn 的那種,還出鍋了幾次 剛開始我不想dfs判斷選出的邊是否構成樹,於是yy了一下,以為只要邊數為 n 1 除了根節點每個點的入度為1且都被訪問過就行了。卻忘了有環的情況 只要...
HNOI2015 落憶楓音
luogu3244 bzoj4011 如果是乙個dag,那麼答案顯然是 prod n deg i 其中 deg i 是點 i 的入度。加上條邊後可能會成環,我們要去掉成環的情況數。考慮乙個環,錯誤的計數只會發生在環上每個點選了自己環上的父親,環外的點隨意。所以對於每個環,多餘的計數是 prod de...