题目
分析
考虑树的情况,对每个结点的儿子按大小排序,从 1 开始 DFS 得到的 DFS 序即为答案。由于 或 ,当 时找到基环树的环暴力枚举删一条边找 DFS 序最小的那个即可。
错因
- 找环的栈在退出的时候忘了
pop
,居然只 MLE 了 28 pts。
代码
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <stack>
#include <vector>
const int MAXN = 5000;
int N, M;
std::vector<int> G[MAXN + 5];
bool Vis[MAXN + 5];
std::stack<int> S;
int Ans[MAXN + 5], Cur[MAXN + 5], Cnt;
void Solve(int u, int fa, int cu, int cv) {
Cur[++Cnt] = u;
for (int i = 0; i < int(G[u].size()); i++) {
int v = G[u][i];
if(v != fa) {
if ((u == cu && v == cv) || (u == cv && v == cu))
continue;
Solve(v, u, cu, cv);
}
}
}
void Dfs(int u, int fa) {
Vis[u] = true, S.push(u);
for (int i = 0; i < int(G[u].size()); i++) {
int v = G[u][i];
if (v != fa) {
if (Vis[v]) {
S.pop();
while (!S.empty()) {
Cnt = 0;
Solve(1, 0, u, S.top());
int res = -1;
for (int j = 1; j <= N && res == -1; j++)
if (Ans[j] != Cur[j])
res = Cur[j] < Ans[j];
if (!Ans[1] || res)
for (int j = 1; j <= N; j++)
Ans[j] = Cur[j];
if (S.top() == v)
break;
u = S.top(), S.pop();
}
for (int i = 1; i <= N; i++)
printf("%d ", Ans[i]);
exit(0);
}
Dfs(v, u);
}
}
S.pop();
}
int main() {
scanf("%d%d", &N, &M);
for (int i = 1; i <= M; i++) {
int u, v; scanf("%d%d", &u, &v);
G[u].push_back(v), G[v].push_back(u);
}
for (int i = 1; i <= N; i++)
std::sort(G[i].begin(), G[i].end());
Dfs(1, 0);
Solve(1, 0, 0, 0);
for (int i = 1; i <= N; i++)
printf("%d ", Cur[i]);
return 0;
}