• prufer 序列 学习笔记


    前言

    上周五看了一下,发现不是很难,今天再看了一眼,把板题做了,顺便看了另外一道(懒得码了)

    正文

    其实很简单,我们定义一颗无根树的 prufer 序列为,钦定任意一个点为根(方便确定父子关系),每次从叶子中选出一个编号最小的点,把它的父亲加入到 prufer 序列中,并删掉该节点。

    不难看出,我们最后会有 (n-2) 个数,而且可以 (nlog n) 求出。并且不同树的 prufer 序列不会相同。实际上我们也可以做到 (Theta(n)) 。大概意思就是指针维护当前编号最小的叶子,然后每次删点的时候把会立马加入到序列的父亲也跟着删掉就好了,具体见代码。

    考虑如何从 prufer 序列转换成一棵树。不难看出,一个点的度数就是 prufer 序列中的出现次数。我们可以先把叶子提出来,每次对于 prufer 序列中的一个点,叶子节点中编号最小的就是它的儿子。然后删掉这个儿子,看是否是叶子即可。时间复杂度 (Theta(nlog n))。不过我们也可以做到 (Theta(n)),与上面类似。

    不难发现的是,对于任意一个 prufer 序列,我们都可以得到相应的一棵树。于是,(n) 个点的生成树个数就是 (n^{n-2}) 个。相应的,我们可以推出每个点度数固定时的生成树个数。

    ( exttt{Code})

    板题传送门

    #include <bits/stdc++.h>
    using namespace std;
    
    #define Int register int
    #define ll long long
    #define MAXN 5000005
    
    template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
    template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
    template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
    
    ll ans;
    int n,m,f[MAXN],seq[MAXN],deg[MAXN];
    
    signed main(){
    	read (n,m);
    	if (m == 1){
    		for (Int i = 1;i < n;++ i) read (f[i]),deg[f[i]] ++;int now = 0;
    		for (Int i = 1,j = 1;i <= n - 2;++ i,++ j){
    			while (deg[j]) ++ j;seq[i] = f[j];
    			while (i <= n - 2 && !-- deg[seq[i]] && seq[i] < j) seq[i + 1] = f[seq[i]],++ i;
    		}
    		for (Int i = 1;i <= n - 2;++ i) ans ^= 1ll * i * seq[i];
    	}
    	else{
    		for (Int i = 1;i < n - 1;++ i) read (seq[i]),deg[seq[i]] ++;seq[n - 1] = n;
    		for (Int i = 1,j = 1;i < n;++ i,++ j){
    			while (deg[j]) j ++;f[j] = seq[i];
    			while (i < n && !-- deg[seq[i]] && seq[i] < j) f[seq[i]] = seq[i + 1],++ i;
    		}
    		for (Int i = 1;i <= n - 1;++ i) ans ^= 1ll * i * f[i];
    	}
    	write (ans),putchar ('
    ');
    	return 0;
    }
    
  • 相关阅读:
    window.open 打开全屏窗口
    H5实现全屏与F11全屏
    泛型 总结
    java 反射
    静态工厂模式
    设计模式---单例模式
    String、List、array相互转换
    将数组转换成list
    将对象转换成json字符串的几种方式
    在map中放入数据时,如果key相同,会替换掉之前的相同key的数据
  • 原文地址:https://www.cnblogs.com/Dark-Romance/p/13770625.html
Copyright © 2020-2023  润新知