题目链接: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;
}