[NOIP 2018] 旅行(暴力) | 错题本

文章目录

题目

[NOIP 2018] 旅行

分析

考虑树的情况,对每个结点的儿子按大小排序,从 1 开始 DFS 得到的 DFS 序即为答案。由于 n = m n = m n = m + 1 n = m + 1 ,当 n = m n = m 时找到基环树的环暴力枚举删一条边找 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;
}

猜你喜欢

转载自blog.csdn.net/C20190102/article/details/107489119