• 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;
    }
    
  • 相关阅读:
    windows 按时自动化任务
    Linux libusb 安装及简单使用
    Linux 交换eth0和eth1
    I.MX6 GPS JNI HAL register init hacking
    I.MX6 Android mmm convenient to use
    I.MX6 GPS Android HAL Framework 调试
    Android GPS GPSBasics project hacking
    Python windows serial
    【JAVA】别特注意,POI中getLastRowNum() 和getLastCellNum()的区别
    freemarker跳出循环
  • 原文地址:https://www.cnblogs.com/Dark-Romance/p/13770625.html
Copyright © 2020-2023  润新知