【题目链接】
【思路要点】
- 考虑树上的情况,每次贪心地走向能够走到的最小位置即可。
- 环套树的搜索树一定是除去一条环边后剩下的一棵树,因此可以枚举除去的环边,再次通过上述贪心找到答案,并取最优解输出。
- 时间复杂度 O ( N 2 ) O(N^2) O(N2) 。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 1e4 + 5; template <typename T> void read(T &x) { x = 0; int f = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -f; for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0'; x *= f; } struct edge {int dest, nxt, num; }; int n, m, head[MAXN], ans[MAXN]; int tot, dis, cnt, now[MAXN]; edge a[MAXN * 2]; vector <int> circle; vector <pair <int, int> > b[MAXN]; int ftype[MAXN], father[MAXN], depth[MAXN]; void work(int pos, int fa) { now[++cnt] = pos; for (int i = head[pos]; i != 0; i = a[i].nxt) if (a[i].num != dis && a[i].dest != fa) work(a[i].dest, pos); } void checkans(int x) { dis = x, cnt = 0; work(1, 0); bool flg = false; for (int i = 1; i <= n; i++) if (now[i] < ans[i]) { flg = true; break; } else if (now[i] > ans[i]) break; if (flg) { for (int i = 1; i <= n; i++) ans[i] = now[i]; } } void dfs(int pos, int fa, int type) { if (circle.size() != 0) return; depth[pos] = depth[fa] + 1; ftype[pos] = type; father[pos] = fa; for (int i = head[pos]; i != 0 && circle.size() == 0; i = a[i].nxt) if (a[i].dest != fa) { if (depth[a[i].dest]) { circle.push_back(a[i].num); int tmp = pos; while (tmp != a[i].dest) { circle.push_back(ftype[tmp]); tmp = father[tmp]; } return; } dfs(a[i].dest, pos, a[i].num); } } bool cmp(pair <int, int> x, pair <int, int> y) { if (x.first == y.first) return x.second < y.second; else return x.first > y.first; } int main() { freopen("travel.in", "r", stdin); freopen("travel.out", "w", stdout); read(n), read(m); for (int i = 1; i <= m; i++) { int x, y; read(x), read(y); b[x].push_back(make_pair(y, i)); b[y].push_back(make_pair(x, i)); } for (int i = 1; i <= n; i++) { sort(b[i].begin(), b[i].end(), cmp); for (unsigned j = 0; j < b[i].size(); j++) a[++tot] = (edge) {b[i][j].first, head[i], b[i][j].second}, head[i] = tot; } ans[1] = n + 1; if (m == n) { dfs(1, 0, 0); for (unsigned i = 0; i < circle.size(); i++) checkans(circle[i]); } else checkans(0); for (int i = 1; i <= n; i++) printf("%d ", ans[i]); printf("\n"); return 0; }