DFS找最小环

DFS找最小环

对于无向无权图,可以直接使用dfs来找最小环,并找出环上的点

例题

http://codeforces.com/contest/1364/problem/D

题意

给出一张图和一个参数k,可以选择完成两个任务中的一个

  • 找到一个独立集恰好有$\lceil k/2 \rceil $个点
  • 找到一个简单环,环长最多为k

题解

对于树形结构,直接判断一下完成任务1即可

对于非树形结构,一定有环,找到最小环,如果最小环长度小于等于k,直接完成任务2,否则在环上隔一个取一个完成任务1即可

代码

在dfs中,满足dep[u]-dep[v]>0即为找到一个环,使用pre记录一下即可还原环上的点

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
struct READ {
    inline char read() {
    #ifdef Artoriax
        return getchar();
    #endif
        const int LEN = 1 << 18 | 1;
        static char buf[LEN], *s, *t;
        return (s == t) && (t = (s = buf) + fread(buf, 1, LEN, stdin)), s == t ? -1 : *s++;
    }
    inline READ & operator >> (char *s) {
        char ch;
        while (isspace(ch = read()) && ~ch);
        while (!isspace(ch) && ~ch) *s++ = ch, ch = read(); *s = '\0';
        return *this;
    }
    inline READ & operator >> (string &s) {
        s = ""; char ch;
        while (isspace(ch = read()) && ~ch);
        while (!isspace(ch) && ~ch) s += ch, ch = read();
        return *this;
    }
    template <typename _Tp> inline READ & operator >> (_Tp&x) {
        char ch, flag;
        for(ch = read(),flag = 0; !isdigit(ch) && ~ch; ch = read()) flag |= ch == '-';
        for(x = 0; isdigit(ch); ch = read()) x = x * 10 + (ch ^ '0');
        flag && (x = -x);
        return *this;
    }
} in;

const int N = 2e5 + 50;
vector<int> G[N];
int pos;
int dep[N];
int pre[N];
int mn = 1e9;
void dfs(int u, int fa, int d) {
    pre[u] = fa;
    dep[u] = d;
    for (int v : G[u]) {
        if (v == fa) continue;
        if (!dep[v]) dfs(v, u, d + 1);
        else if (dep[u] - dep[v] > 0 && dep[u] - dep[v] + 1 < mn){
            mn = dep[u] - dep[v] + 1;
            pos = u;
        }
    }
}
int main() {
    int n, m, k; in >> n >> m >> k;
    for (int i = 1; i <= m; i++) {
        int u, v; in >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(1, 0, 1);
    if (m == n - 1) {
        vector<int> res[2];
        for (int i = 1; i <= n; i++) {
            res[dep[i] & 1].push_back(i);
        }
        puts("1");
        int sz = (k + 1) / 2;
        if (res[0].size() < res[1].size()) {
            for (int i = 0; i < sz; i++) printf("%d ", res[1][i]);
        }
        else {
            for (int i = 0; i < sz; i++) printf("%d ", res[0][i]);
        }
        return 0;
    }
    if (mn <= k) {
        puts("2");
        printf("%d\n", mn);
        while (mn--) {
            printf("%d ", pos);
            pos = pre[pos];
        }
    }
    else {
        puts("1");
        for (int i = 0; i < (k + 1) / 2; i++) {
            printf("%d ", pos);
            pos = pre[pre[pos]];
        }
    }
    return 0;
}
posted @ 2020-09-10 23:07  Artoriax  阅读(470)  评论(0编辑  收藏  举报