Prufer序列

Prufer序列是一种将树和序列双向映射的方式

构造方法:

  1. 统计树上结点的度数 \(degree_i\)
  2. 找到所有叶子结点 \((degree_i==1)\) 中编号最小的 \(x\),输出 \(fa_x\)
  3. \(fa_x\) 的度数减 \(1\)
  4. 重复步骤 \(2-3\),直到只剩下 \(n-2\) 个元素为止

性质:

  1. 树上结点编号在prufer序中出现的次数为 \(degree_x-1\)
  2. 最后剩下的 \(2\) 个点中,一定包含编号为 \(n\) 的结点

下面为获得prufer序的代码:

void to_prufer()
{
	for(int i=1;i<=n;i++)du[i]++,du[fa[i]]++;
	int cur;
	for(int i=1;i<=n;i++)if(du[i]==1)
	{
		cur=i;
		break;
	}
	int leaf=cur;
	for(int i=1;i<=n-2;i++)
	{
		int f=fa[leaf];
		prufer[i]=f;
		du[f]--;
		if(du[f]==1 && f<cur)
		{
			leaf=f;
			continue;
		}
		cur++;while(du[cur]!=1) cur++;
		leaf=cur;
	}
}
//要以n为根

下面为获得树的代码:

void to_tree()
{
	for(int i=1;i<=n;i++) du[i]=1;
	for(int i=1;i<=n-2;i++) du[prufer[i]]++;
	int cur;
	for(int i=1;i<=n;i++)if(du[i]==1)
	{
		cur=i;
		break;
	}
	int leaf=cur;
	for(int i=1;i<=n-2;i++)
	{
		int f=fa[leaf]=prufer[i];
		du[f]--;
		if(du[f]==1 && f<cur)
		{
			leaf=f;
			continue;
		}
		++cur;while(du[cur]!=1) cur++;
		leaf=cur;
	}
	fa[leaf]=n;
}

应用:

  1. \(n\) 个点的无向完全图的不同生成树的个数 \(n^{n-2}\)
  2. \(n\) 个点的无根树的方案数 \(n^{n-2}\)
  3. \(n\) 个点的有根树的方案数 \(n^{n-1}\)
  4. \(n\) 个点,第 \(i\) 个点的度数为 \(degree_i\) 的无根树的方案数 \(\frac{(n-2)!}{\prod_{i=1}^{n}{(degree_i-1)!}}\)
posted @ 2024-01-30 21:00  noipwen  阅读(24)  评论(0)    收藏  举报