zoukankan      html  css  js  c++  java
  • DFS找最小环

    DFS找最小环

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

    例题

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

    题意

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

    • 找到一个独立集恰好有$lceil k/2 ceil $个点
    • 找到一个简单环,环长最多为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 = '';
            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
    ", 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;
    }
    
  • 相关阅读:
    Qt 学习
    Qt 串口连接
    GitKraken使用教程-基础部分(9)
    GitKraken使用教程-基础部分(8)
    GitKraken使用教程-基础部分(7)
    GitKraken使用教程-基础部分(6)
    GitKraken使用教程-基础部分(5)
    GitKraken使用教程-基础部分(4)
    GitKraken使用教程-基础部分(3)
    C++ 利用template给函数中的变量赋初值
  • 原文地址:https://www.cnblogs.com/artoriax/p/13649011.html
Copyright © 2011-2022 走看看