Codeforces Round #161 (Div. 2) D. Cycle in Graph(无向图中找指定长度的简单环)

时间:2023-02-03 08:10:03

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