P7920 Permutation
不清楚是不是正解反正能过
分析问题
这个题可能乍一看很高大上排列,同构,字典序 blablabla
然而我们稍微模拟一下,很容易建立出一个更直观的模型
给这个树的节点填上
我怀疑那个样例故意往图上填下标就是为了不让这个模型太过明显
(接下来我们以
首先堆顶肯定是 根据样例显然有可能
(欢迎各位大佬在评论区留言给出更严谨的说明 wtcl)
好了细心的同学可能已经发现了,我们写的是 dfs1
那势必有 dfs2
开始换根
不难发现如果我们对每个节点都作为根跑一次 dfs1 势必会 T
换根的思维难度不高,然而我自己的实现丑的要死
假设此时我们处理好了
暴力地遍历
但是停一下!在此之前,要二分地查找
(由于我们似乎不能破坏已经排序好的数组,所以我只能用这种方式粗暴地解决问题)
然后我们故技重施,暴力查找
由于前面 cmp 函数写丑了所以这里会有一些 n + 2, n + 3 之类的数,本身并没有特别的意义。
int ansi;
vector<int> F[5007];
void dfs2(int x) {
F[fa[x]].clear(); F[fa[x]].push_back(n - sz[x]);
f[n + 3] = F[fa[fa[x]]];
int pos = lower_bound(g[fa[x]].begin(), g[fa[x]].end(), n + 3, cmp) - g[fa[x]].begin();
for(int i = 0; i < pos; ++i) {
if(g[fa[x]][i] == x || g[fa[x]][i] == fa[fa[x]])continue;
for(int j = 0; j < f[g[fa[x]][i]].size(); ++j) {
F[fa[x]].push_back(f[g[fa[x]][i]][j]);
}
}
for(int j = 0; j < F[fa[fa[x]]].size(); ++j) {
F[fa[x]].push_back(F[fa[fa[x]]][j]);
}
for(int i = pos; i < g[fa[x]].size(); ++i) {
if(g[fa[x]][i] == x || g[fa[x]][i] == fa[fa[x]])continue;
for(int j = 0; j < f[g[fa[x]][i]].size(); ++j) {
F[fa[x]].push_back(f[g[fa[x]][i]][j]);
}
}
f[n + 3] = F[fa[x]]; f[n + 2].clear(); f[n + 2].push_back(n);
pos = lower_bound(g[x].begin(), g[x].end(), n + 3, cmp) - g[x].begin();
for(int i = 0; i < pos; ++i) {
if(g[x][i] == fa[x])continue;
for(int j = 0; j < f[g[x][i]].size(); ++j) {
f[n + 2].push_back(f[g[x][i]][j]);
}
}
for(int j = 0; j < F[fa[x]].size(); ++j) {
f[n + 2].push_back(F[fa[x]][j]);
}
for(int i = pos; i < g[x].size(); ++i) {
if(g[x][i] == fa[x])continue;
for(int j = 0; j < f[g[x][i]].size(); ++j) {
f[n + 2].push_back(f[g[x][i]][j]);
}
}
if(cmp(n + 2, n + 1)) {
ansi = x; f[n + 1] = f[n + 2];
}
for(int i = 0; i < g[x].size(); ++i) {
if(g[x][i] != fa[x]) dfs2(g[x][i]);
}
}
完结撒花!
gg,我们还没有输出
int ans[5007];
void dfs(int x) {
static int cnt = 0;
ans[x] = ++cnt;
for(int i = g[x].size() - 1; i >= 0; --i) {
if(g[x][i] == fa[x]) continue;
dfs(g[x][i]);
}
}
void sfd(int x) {
printf("%d ", ans[x]);
for(int i = 0; i < g[x].size(); ++i) {
if(g[x][i] == fa[x]) continue;
sfd(g[x][i]);
}
}
signed main() {
scanf("%d", &n);
for(int i = 1; i < n; ++i) {
int a, b; scanf("%d %d", &a, &b);
g[a].push_back(b); g[b].push_back(a);
}
dfs1(1); ansi = 1;
f[n + 1] = f[1];
for(int i = 0; i < g[1].size(); ++i) dfs2(g[1][i]);
fa[ansi] = 0; dfs1(ansi);
dfs(ansi); sfd(ansi);
return 0;
}
(两个 dfs 用来输出看上去不太优雅,但是它能解决这道题)