[assignment] #1 CF512D

Posted by disenopop on Thu, 27 Jan 2022 11:53:54 +0100

CF512D Fox And Travelling

Title Description

Click here to see the question

Give an undirected graph. Each time you can select a point of degree \ (\ leq 1 \) and delete it.

Ask how many sequences delete \ (K \) points for \ (k=0,1,2...n \), and the answer module \ (10 ^ 9 + 9 \)

\(n\leq 100,m\leq \frac{n(n-1)}{2}\)

solution

Because only the points of degree \ (\ leq 1 \) can be deleted, the ring has nothing to do with the deletion sequence. Then we can get a forest after removing the ring. This process can be realized by topological sorting, and the points without topological deletion do not need to be considered.

But the trees in this forest are different, because if a tree is connected to the ring, you must take the linked point as the root and finally select it. But if the tree is not connected to the ring, there is no root. So this forest is a mixture of rooted and rootless trees.

First, consider what to do with a rooted tree. The tree shape \ (dp \) is obvious, \ (dp[u][i] \) indicates that \ (I \) points are selected in the point \ (U \), and then the tree knapsack board.

How to do rootless trees is the key. According to the routine I summarized before, we can enumerate roots, make tree shape \ (dp \) according to the method of rooted trees, and then sum the results. This will obviously be heavy. The highlight of this topic is to consider how many times a scheme has been heavy (direct but practical method). For the scheme with \ (I \) points selected, since these \ (I \) points must be at the edge of the tree, selecting other \ (size-i \) points as the root will be calculated into the scheme, so we can divide it by \ (size-i \).

Time complexity \ (O(n^3) \), since I don't study polynomials, the better methods will not be explained.

Details: for the topological sorting of undirected graphs, you'd better add an access flag, and then plug it into the queue when \ (deg\leq 1 \).

#include <cstdio>
#include <iostream>
#include <queue>
using namespace std;
const int M = 105;
const int MOD = 1e9+9;
#define int long long
int read()
{
	int x=0,f=1;char c;
	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}
int n,m,tot,f[M],d[M],b[M],inv[M],fac[M],vis[M];
int dp[M][M],g[M],h[M],s[M],zinv[M],siz[M];
struct edge {int v,next;}e[M*M];
void add(int &x,int y) {x=(x+y)%MOD;}
void init(int n)
{
	fac[0]=inv[0]=inv[1]=1;
	for(int i=2;i<=n;i++) inv[i]=inv[MOD%i]*(MOD-MOD/i)%MOD;
	for(int i=0;i<=n;i++) zinv[i]=inv[i];
	for(int i=2;i<=n;i++) inv[i]=inv[i-1]*inv[i]%MOD;
	for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%MOD;
}
int C(int n,int m)
{
	if(n<m || m<0) return 0;
	return fac[n]*inv[m]%MOD*inv[n-m]%MOD;
}
void tpsort()
{
	queue<int> q;
	for(int i=1;i<=n;i++)
		if(d[i]<=1) vis[i]=1,q.push(i);
	while(!q.empty())
	{
		int u=q.front();q.pop();
		for(int i=f[u];i;i=e[i].next)
		{
			int v=e[i].v;d[v]--;
			if(d[v]<=1 && !vis[v]) vis[v]=1,q.push(v);
		}
	}
}
void dfs(int u,int rt)
{
	b[u]=rt;s[rt]++;
	for(int i=f[u];i;i=e[i].next)
	{
		int v=e[i].v;
		if(!b[v] && !d[v]) dfs(v,rt);
	}
}
void get(int u,int fa)
{
	for(int i=0;i<=n;i++) dp[u][i]=0;
	dp[u][0]=1;siz[u]=1;
	for(int i=f[u];i;i=e[i].next)
	{
		int v=e[i].v;
		if(v==fa || b[u]!=b[v]) continue;
		get(v,u);
		for(int j=siz[u];j>=0;j--)
			for(int k=1;k<=siz[v];k++)
				add(dp[u][j+k],dp[u][j]*dp[v][k]%MOD*C(j+k,j));
		siz[u]+=siz[v];
	}
	dp[u][siz[u]]=dp[u][siz[u]-1];
}
signed main()
{
	n=read();m=read();init(n);
	for(int i=1;i<=m;i++)
	{
		int u=read(),v=read();d[u]++;d[v]++;
		e[++tot]=edge{u,f[v]},f[v]=tot;
		e[++tot]=edge{v,f[u]},f[u]=tot;
	}
	tpsort();
	for(int i=1;i<=n;i++)
		if(d[i]==1) dfs(i,i);
	for(int i=1;i<=n;i++)
		if(!d[i] && !b[i]) dfs(i,i);
	g[0]=1;
	for(int i=1;i<=n;i++) if(i==b[i])
	{
		for(int j=0;j<=n;j++) h[j]=0;
		if(d[i]==1)
		{
			get(i,0);
			for(int j=0;j<=s[i];j++) h[j]=dp[i][j];
		}
		else
		{
			for(int o=1;o<=n;o++) if(b[o]==i)
			{
				get(o,0);
				for(int j=0;j<=s[i];j++)
					add(h[j],dp[o][j]);
			}
			for(int j=0;j<=s[i];j++)
				h[j]=h[j]*zinv[s[i]-j]%MOD;
		}
		for(int j=n;j>=0;j--)
			for(int k=1;k<=s[i] && j+k<=n;k++)
				add(g[j+k],g[j]*h[k]%MOD*C(j+k,j));
	}
	for(int i=0;i<=n;i++)
		printf("%lld\n",g[i]);
}