【BZOJ】【4011】【HNOI2015】落忆枫音
拓扑排序+DP
题解:http://blog.csdn.net/PoPoQQQ/article/details/45194103
http://www.cnblogs.com/mmlz/p/4448742.html
通过转化……路径外的$degree_i$的乘积转化成所有点的degree之积除以路径内的,所以用到逆元……
PoPoQQQ的线性筛逆元好神奇啊……>_< OrzOrz
1 /************************************************************** 2 Problem: 4011 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:784 ms 7 Memory:10648 kb 8 ****************************************************************/ 9 10 //Huce #7 A 11 #include<vector> 12 #include<cstdio> 13 #include<cstdlib> 14 #include<cstring> 15 #include<iostream> 16 #include<algorithm> 17 #define rep(i,n) for(int i=0;i<n;++i) 18 #define F(i,j,n) for(int i=j;i<=n;++i) 19 #define D(i,j,n) for(int i=j;i>=n;--i) 20 using namespace std; 21 22 int getint(){ 23 int v=0,sign=1; char ch=getchar(); 24 while(ch<'0'||ch>'9') {if (ch=='-') sign=-1; ch=getchar();} 25 while(ch>='0'&&ch<='9') {v=v*10+ch-'0'; ch=getchar();} 26 return v*sign; 27 } 28 typedef long long LL; 29 const int N=200010,P=1e9+7,INF=~0u>>2; 30 /*******************template********************/ 31 int to[N<<1],next[N<<1],head[N],cnt; 32 void add(int x,int y){ 33 to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt; 34 } 35 int n,m,s,t,du[N],in[N]; 36 LL inv[N],f[N],ans=1; 37 void Linear_Shaker(){ 38 int i; 39 for(inv[1]=1,i=2;i<=m+1;i++) 40 inv[i]=(P-P/i)*inv[P%i]%P; 41 } 42 int Q[N]; 43 void tpsort(){ 44 int l=0,r=-1; 45 f[t]=ans; 46 F(i,1,n) if (!du[i]) Q[++r]=i; 47 while(l<=r){ 48 int x=Q[l++]; 49 f[x]=(f[x]*inv[du[x]])%P; 50 for(int i=head[x];i;i=next[i]){ 51 (f[to[i]]+=f[x])%=P; 52 if (!--in[to[i]]) Q[++r]=to[i]; 53 } 54 } 55 } 56 int main(){ 57 #ifndef ONLINE_JUDGE 58 freopen("A.in","r",stdin); 59 // freopen("output.txt","w",stdout); 60 #endif 61 n=getint(); m=getint(); s=getint(); t=getint(); 62 Linear_Shaker(); 63 int x,y; 64 F(i,1,m){ 65 x=getint(); y=getint(); 66 add(x,y); 67 in[y]++; du[y]++; 68 } 69 du[t]++; 70 F(i,2,n) ans=(ans*du[i])%P; 71 if (t==1){ 72 printf("%lld\n",ans); 73 }else{ 74 tpsort(); 75 printf("%lld\n",(ans-f[s]+P)%P); 76 } 77 return 0; 78 }
4011: [HNOI2015]落忆枫音
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 133 Solved: 64
[Submit][Status][Discuss]
Description
【问题描述】
不妨假设枫叶上有 n个穴位,穴位的编号为 1 ~ n。有若干条有向的脉络连接
着这些穴位。穴位和脉络组成一个有向无环图——称之为脉络图(例如图 1),穴
位的编号使得穴位 1 没有从其他穴位连向它的脉络,即穴位 1 只有连出去的脉络;
由上面的故事可知,这个有向无环图存在一个树形子图,它是以穴位 1为根的包含
全部n个穴位的一棵树——称之为脉络树(例如图 2和图 3给出的树都是图1给出
的脉络图的子图);值得注意的是,脉络图中的脉络树方案可能有多种可能性,例
如图2和图 3就是图 1给出的脉络图的两个脉络树方案。
脉络树的形式化定义为:以穴位 r 为根的脉络树由枫叶上全部 n个穴位以及 n
- 1 条脉络组成,脉络树里没有环,亦不存在从一个穴位连向自身的脉络,且对于
枫叶上的每个穴位 s,都存在一条唯一的包含于脉络树内的脉络路径,使得从穴位
r 出发沿着这条路径可以到达穴位 s。
现在向脉络图添加一条与已有脉络不同的脉络(注意:连接 2个穴位但方向不
同的脉络是不同的脉络,例如从穴位3到4的脉络与从4到3的脉络是不同的脉络,
因此,图 1 中不能添加从 3 到 4 的脉络,但可添加从 4 到 3 的脉络),这条新脉络
可以是从一个穴位连向自身的(例如,图 1 中可添加从 4 到 4 的脉络)。原脉络图
添加这条新脉络后得到的新脉络图可能会出现脉络构成的环。
请你求出添加了这一条脉络之后的新脉络图的以穴位 1 为根的脉络树方案数。
由于方案可能有太多太多,请输出方案数对 1,000,000,007 取模得到的结果。
Input
输入文件的第一行包含四个整数 n、m、x和y,依次代表枫叶上的穴位数、脉
络数,以及要添加的脉络是从穴位 x连向穴位y的。
接下来 m行,每行两个整数,由空格隔开,代表一条脉络。第 i 行的两个整数
为ui和vi,代表第 i 条脉络是从穴位 ui连向穴位vi的。
Output
输出一行,为添加了从穴位 x连向穴位 y的脉络后,枫叶上以穴位 1 为根的脉
络树的方案数对 1,000,000,007取模得到的结果。
Sample Input
4 4 4 3
1 2
1 3
2 4
3 2
1 2
1 3
2 4
3 2
Sample Output
3
HINT
对于所有测试数据,1 <= n <= 100000,n - 1 <= m <= min(200000, n(n – 1) / 2),
1 <= x, y, ui, vi <= n。