luogu P3244 [HNOI2015]落忆枫音
LINK:落忆枫音
窝是不会告诉你 做这道题也是和心上秋一样被题面所吸引的
遗憾的是 这是一个剧情类游戏不是动漫 看起来很好看的样子 不过看不了...
题目给了一张有向无环图。定义了这个有向无环图的生成树形子图 的样子:n-1条边 不存在从自身到自身的边 从1到所有点都有路径存在的外向树形图。
问 随便加一条边 可以是自环 但是不能和图中的边重合(和某条边两端一样且方向一样) 然后这个图的生成树形子图的个数和。
看起来是一个复杂度的 计数题目。首先考虑 加的边如果是自环 那么这个自环还是要去掉的。
所以求的其实是 原图中的生成树的个数。
由于是一棵有向树 所以先判断一下从1出发是否可以到所有的点。
所有点都能到 说明 所有的点都将被某个点所指 且不存在环的关系 因为保证了是有向无环图。
不难发现此时方案为 除了1之外的所有的点的度数乘积。(好像刚才的那个特判是不必要的。如果不连通说明必然还有一个点的入度为0 方案仍然是0.
加上一条边 如果形不成环 那么说明 此时把边加里面 然后还是所有点的度数的乘积。
如果形成了环 如果此时考虑答案的增量 会非常的麻烦 或者说统计不了答案的增量。
考虑 总答案 可以求出 考虑不合法方案 那其实就是有环的方案 把这些环的方案都求出来减掉即可。
const int MAXN=200000;
int n,m,xx,yy,l,r,len,flag;
int ru[MAXN],w[MAXN],vis[MAXN];
ll inv[MAXN],ans,ww,c,f[MAXN];
int lin[MAXN],ver[MAXN],nex[MAXN],q[MAXN];
inline void add(int x,int y)
{
ver[++len]=y;
nex[len]=lin[x];
lin[x]=len;
++ru[y];++w[y];
}
inline void topsort()
{
l=r=0;
q[++r]=1;f[yy]=ww;
while(++l<=r)
{
int x=q[l];f[x]=f[x]*inv[ru[x]]%mod;
go(x)
{
f[tn]=(f[tn]+f[x])%mod;
--w[tn];if(!w[tn])q[++r]=tn;
}
}
ans=(ww-f[xx]+mod)%mod;
}
int main()
{
freopen("1.in","r",stdin);
get(n);get(m);get(xx);get(yy);
inv[1]=1;++ru[yy];
rep(1,m,i)
{
int x,y;
get(x);get(y);
add(x,y);
if(i!=1)inv[i]=(mod-mod/i)*inv[mod%i]%mod;
}
ww=1;rep(2,n,i)ww=ww*ru[i]%mod;
if(yy==1){putl(ww);return 0;}
topsort();putl(ans);
return 0;
}