提供一种与大佬们类似的思路:
按照题目所给的建图,例如读入为 xi,yi,则建一条从 xi 到 i 的边,边权为 yi。
建完图后进行一个类似于缩点的行为(赛时没想到)。遍历每个点的出边,若其中有两条的边权相同,则合并,用一个 vector 去记录有多少个点合并到这个点里,随后将第二个点的所有孩子换到第一个点,并记录哪些点没替换了,最后 dfs 遍历输出即可。
#include <bits/stdc++.h>
using namespace std;
int n, d[300005], rem[300005];
vector<pair<int, int> > g[300005];
vector<int> t[300005];
void dfs(int u){
if(rem[u]){
return;
}
sort(g[u].begin(), g[u].end());
if(u){
printf("%d ", u);
sort(t[u].begin(), t[u].end());
for(auto v : t[u]){
printf("%d ", v);
}
}
for(auto v : g[u]){
dfs(v.second);
}
}
int main(){
scanf("%d", &n);
for(int i = 1;i<=n;i++){
int x, y;
scanf("%d %d", &x, &y);
g[x].push_back(make_pair(y, i));
}
for(int i = 0;i<=n;i++){
sort(g[i].begin(), g[i].end());
if(g[i].size()<=1){
continue;
}
int m = g[i].size(), syg = 0;
for(int j = 1;j<=m - 1;j++){
if(g[i][j].first!=g[i][j - 1].first){
syg = j;
}else{
for(auto k : t[g[i][j].second]){
t[g[i][syg].second].push_back(k);
}
t[g[i][j].second].clear();
t[g[i][syg].second].push_back(g[i][j].second);
for(auto k : g[g[i][j].second]){
g[g[i][syg].second].push_back(k);
}
g[g[i][j].second].clear();
rem[g[i][j].second] = 1;
}
}
}
dfs(0);
return 0;
}
居然只是个黄,我还是太菜了呜呜~
1875

被折叠的 条评论
为什么被折叠?



