General
 
 
# Author Problem Lang Verdict Time Memory Sent Judged  
97316216 Practice:
Linshey
512D - 17 GNU C++11 Accepted 46 ms 18604 KB 2020-11-01 14:25:30 2020-11-01 14:25:30
→ Source

/*
简要题解:
显然环上的点不可取,连接了两个以上环的树不可取。
用类似拓扑排序的做法,把图上所有的能取的联通块弄出来。
这些联通块都是以树的形式出现的,可以分成两种树,
一种独立的无根树,一种是根接在环上的有根树。
对于有根树,我们知道一个点能遍历,当且仅当整个子树已经遍历了。
设f[i][j]表示i子树遍历了j个点的方案数,
状态转移方程考虑怎么把儿子接到父亲上,有
f[i][j] * f[son][k] * C(j, j+k) --> f'[i][j + k]
因为实际上就是把这些已经确定顺序的点交叉拼在一起,从j+k个顺序中,
选出j个作为原来放的顺序,所以要乘上组合数;
对于无根树就非常难办了,但通过xht大佬的题解我搞懂了:
无根树肯定有一个点是最后遍历的点,那么我们枚举这个点,
就转化为了有根树的情况;一个遍历了k个点遍历方式,
一共会被这个过程计算(size - k)遍,即排列的这些点不能作为根,
剩下的点都能被上述过程作为根,时间复杂度O(n^3).

*/
#include <cstdio>
#include <cstring>
#include <iostream>
#define LL long long
#define rint register int

using namespace std;
const int maxn = 505;
const int mod = 1e9 + 9;

namespace IO
{

	char buf[1 << 23], * p1 = buf, * p2 = buf, obuf[1 << 23], * O = obuf;

	//#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)

	struct Fread { } fin, fout;

	int f__; char ch_, Endl = '\n';

	inline Fread& operator >>(Fread& F, int& a)
	{
		a = 0; f__ = 1; ch_ = getchar();
		while (ch_ < '0' || ch_ > '9')
		{
			if (ch_ == '-') f__ = -1;
			ch_ = getchar();
		}
		while (ch_ >= '0' && ch_ <= '9')
		{
			a = (a << 3) + (a << 1) + (ch_ ^ 48);
			ch_ = getchar();
		}
		a *= f__; return F;
	}

	Fread& operator <<(Fread& F, const int& a)
	{
		if (a > 9) F << (a / 10);
		*O++ = a % 10 + '0';
		return F;
	}

	Fread& operator <<(Fread& F, const char& b)
	{
		*O++ = b;
		return F;
	}
};
namespace graph
{

	struct Edge
	{
		int to, nx;
	};

	Edge edge[maxn];
	int head[maxn], tot;

	void add(int x, int y)
	{
		++tot;
		edge[tot].to = y;
		edge[tot].nx = head[x];
		head[x] = tot;
	}
}
namespace math
{
	int inv[maxn], fac[maxn], fiv[maxn];

	void prework()
	{
		inv[0] = inv[1] = 1;
		for (int i = 2; i < maxn; i++)
		{
			inv[i] = ((LL)mod - mod / i) * inv[mod % i] % mod;
		}
		fac[0] = fac[1] = 1;
		fiv[0] = fiv[1] = 1;
		for (int i = 2; i < maxn; i++)
		{
			fiv[i] = (LL)fiv[i - 1] * inv[i] % mod;
			fac[i] = (LL)fac[i - 1] * i % mod;
		}
	}

	inline int C(int y, int x)
	{
		return (LL)fac[x] * fiv[y] % mod * fiv[x - y] % mod;
	}
}

using namespace math;
using namespace graph;
using namespace IO;

int n, m, deg[maxn];

void read()
{
	fin >> n >> m;
	for (int i = 1; i <= m; i++)
	{
		int a, b;
		fin >> a >> b;
		add(a, b); deg[a]++;
		add(b, a); deg[b]++;
	}
}

int tag[maxn], lst[maxn];

void bfs()
{
	rint i, a, b;
	int q[maxn], vis[maxn], hd, tl;
	hd = tl = 0;
	for (i = 1; i <= n; i++)
	{
		if (deg[i] <= 1)
		{
			q[++tl] = i;
			tag[i] = true;
		}
	}
	while (hd != tl)
	{
		a = q[++hd];
		for (i = head[a]; i; i = edge[i].nx)
		{
			b = edge[i].to;
			if (!tag[b] && --deg[b] <= 1)
			{
				tag[b] = true;
				q[++tl] = b;
			}
		}
	}
	for (i = 1; i <= n; i++)
	{
		deg[i] = 0;
		for (a = head[i]; a; a = edge[a].nx)
		{
			b = edge[a].to;
			if (tag[b]) deg[i]++;
			else lst[i] = true;
		}
	}
}

int clr[maxn], typ[maxn], ncr;

void dfs(int x)
{
	if (clr[x]) return;
	if (!tag[x]) return;
	clr[x] = ncr;
	for (int i = head[x]; i; i = edge[i].nx)
	{
		int s = edge[i].to;
		dfs(s);
	}
}

int sze[maxn], f[maxn][maxn], g[maxn][maxn];

void dp(int x, int fa)
{
	int temp[maxn];
	memset(f[x], 0, sizeof f[x]);
	memset(temp, 0, sizeof temp);
	f[x][0] = 1; sze[x] = 0;
	for (int i = head[x]; i; i = edge[i].nx)
	{
		int s = edge[i].to;
		if (s == fa) continue;
		if (!tag[s]) continue;
		dp(s, x);
		for (int j = 0; j <= sze[x]; j++)
		{
			for (int k = 0; k <= sze[s]; k++)
			{
				(temp[j + k] += (LL)f[x][j] * f[s][k] % mod * C(k, j + k) % mod) %= mod;
			}
		}
		sze[x] += sze[s];
		for (int j = 0; j <= sze[x]; j++)
		{
			f[x][j] = temp[j];
			temp[j] = 0;
		}
	}
	sze[x]++;
	f[x][sze[x]] = (LL)f[x][sze[x] - 1] % mod;
}

int h[2][maxn];

int main()
{
	read();
	bfs();
	prework();
	rint i, j, k;
	for (i = 1; i <= n; i++)
	{
		if (!tag[i])
		{
			continue;
		}
		if (!clr[i])
		{
			++ncr;
			dfs(i);
		}
		if (lst[i])
		{
			typ[clr[i]] = true;
		}
	}
	for (i = 1; i <= n; i++)
	{
		if (!tag[i]) continue;
		if (!typ[clr[i]] || lst[i])
		{
			dp(i, i);
			for (j = 0; j <= n; j++)
			{
				(g[clr[i]][j] += (LL)f[i][j] * (!lst[i] ? inv[sze[i] - j] : 1) % mod) %= mod;
			}
		}
	}
	int dir = 0;
	h[dir][0] = 1;
	for (i = 1; i <= ncr; i++)
	{
		memset(h[dir ^ 1], 0, sizeof h[dir ^ 1]);
		for (j = 0; j <= n; j++)
		{
			for (k = 0; k + j <= n; k++)
			{
				(h[dir ^ 1][j + k] += (LL)h[dir][j] * g[i][k] % mod * C(j, j + k) % mod) %= mod;
			}
		}
		dir ^= 1;
	}
	for (i = 0; i <= n; i++) fout << h[dir][i] << Endl;
	fwrite(obuf, O - obuf, 1, stdout);
	return 0;
}
?
Time: ? ms, memory: ? KB
Verdict: ?
Input
?
Participant's output
?
Jury's answer
?
Checker comment
?
Diagnostics
?
Click to see test details