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;
}
原文地址:https://www.cnblogs.com/chdy/p/12608716.html