题目: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;
}