2419. prufer序列

题目:https://www.acwing.com/problem/content/description/2421/
题意: 求prufer

bug: 赋值运算:先算的是后边,再看前面
for instance : “f[p[i]] = p[i + 1], i++;” != “f[p[i]] = p[++i]”

代码:

#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
const double DINF = 1e20;
const double eps = 1e-8;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int N = 1e5 + 50;

int n, m;
int f[N], d[N], p[N];

inline void Tree2prufer()
{
    
    
    for (int i = 1; i < n; i++) {
    
    
        cin >> f[i]; d[f[i]]++;
    }

    for (int i = 0, j = 1; i < n - 2; j++) {
    
     // j++,因为j是已经加入的结点,所以它的d[j]一定是零,因此
                                             // 需要把这个点移到下一位
        while (d[j]) j++;                    // 但是下一位不一定是可行的点,所以要往后找。
        p[i++] = f[j]; // 从前往后找第一个度为零的
        while (i < n - 2 && --d[p[i - 1]] == 0 && p[i - 1] < j) p[i++] = f[p[i - 1]]; 
            // 如果把这个j点去掉之后看是否会出现一个比现在加入的j要小的father,如果有,则直接加入。
            // 去一个点只会减少一条边,因为是树,所以while循环的时候只看j的father结点,也就是
            // p[i - 1]的结点。
    }

    for (int i = 0; i < n - 2; i++) cout << p[i] << ' ';
    cout << endl;
}

inline void Prufer2tree()
{
    
    
    for (int i = 1; i <= n - 2; i++) {
    
    
        cin >> p[i]; d[p[i]]++;
    }

    p[n - 1] = n; // 必然的结果
    for (int i = 1, j = 1; i < n; i++, j++) {
    
    
        while (d[j]) j++;  // 从前往后找到第一个度为零的结点。
        f[j] = p[i]; // 本来是p序列的值等于j的父节点,现在是j的父节点等于p的值
        while (i < n - 1 && --d[p[i]] == 0 && p[i] < j) f[p[i]] = p[i + 1], i++;
        // 然后把j的父节点的度减去,那么如果它是叶,并且比j的小的话,和第一种是一样的
        // 此时j的父节点的father应该是p序列的下一个,因为如果前边的father结点是的话,
        // 一定是加入的p序列里,即: p[i + 1] = f[p[i]], 此时正好相反。
    }

    for (int i = 1; i <= n - 1; i++) cout << f[i] << ' ';
    cout << endl;
}

signed main(int argc, char* argv[])
{
    
    
    cin >> n >> m;

    if (m == 1) Tree2prufer();
    else Prufer2tree();

    return 0;
}

Guess you like

Origin blog.csdn.net/YingShen_xyz/article/details/115114386