题目链接:http://codeforces.com/problemset/problem/263/D
思路:一遍dfs即可,dp[u]表示当前遍历到节点u的长度,对于节点u的邻接点v,如果v没有被访问过,则继续访问,否则计算dp[u] - dp[v] + 1是否大于等于K + 1,如果是,就说明找到了这样一个符合要求的环,然后将回退,回退的时候将环上的节点标记即可,否则,就继续找。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <deque> #define REP(i, a, b) for (int i = (a); i < (b); ++i) #define FOR(i, a, b) for (int i = (a); i <= (b); ++i) using namespace std; const int MAX_N = (100000 + 10); int N, M, K, st, found, flag[MAX_N], vis[MAX_N], dp[MAX_N]; vector<int > g[MAX_N]; vector<int > ans; void dfs(int u, int father, int len) { vis[u] = 1; dp[u] = len; REP(i, 0, (int)g[u].size()) { int v = g[u][i]; if (v == father) continue; if (vis[v] && dp[u] - dp[v] + 1 >= K + 1) { st = v; flag[u] = 1; ans.push_back(u); return; } if (!vis[v]) dfs(v, u, len + 1); if (st) { if (found) return; if (u == st) found = 1; ans.push_back(u); flag[u] = 1; return; } } } int main() { while (cin >> N >> M >> K) { ans.clear(); FOR(i, 1, N) flag[i] = vis[i] = 0, g[i].clear(); while (M--) { int u, v; cin >> u >> v; g[u].push_back(v); g[v].push_back(u); } st = found = 0; dfs(1, -1, 0); cout << (int)ans.size() << endl; REP(i, 0, (int)ans.size()) { if (i == (int)ans.size() - 1) cout << ans[i] << endl; else cout << ans[i] << ' '; } } return 0; }