Codeforces 1325F Ehab's Last Theorem

题目大意

给出一幅 \(n\) 个点,\(m\) 条边的无向连通图。让你找出至少有 \(\lceil \sqrt{n} \rceil\) 个点的简单环,或正好有 \(\lceil \sqrt{n} \rceil\) 个点的最大独立集。(两者选其一)

如找的是最大独立集,输出1并输出最大独立集的顶点。
如找的是环,输出2,输出环的顶点个数并输出环的所有顶点。

\((5 \le n \le 10^5, n-1 \le m \le 2 \cdot 10^5)\)

题解

对于无向图的连通性问题,我们首先考虑它的DFS树。
若结点 \(u\) 有大于等于 \(\lceil\sqrt n\rceil-1\) 条后向边,则一定存在长度大于等于 \(\lceil\sqrt n\rceil\) 的简单环。
否则若当前构造的独立集中没有点与 \(u\) 相邻,我们就把结点 \(u\) 加入独立集。
若最终没有找到大于 \(\lceil\sqrt n\rceil\) 的简单环,那么构造出的独立集一定是大于等于 \(\lceil\sqrt n\rceil\) 的。因为选择一个点加入独立集至多只会导致和它相邻的 \(\lceil\sqrt n\rceil-2\) 个点无法被加入独立集。

Code

#include <bits/stdc++.h>
using namespace std;

#define RG register int
#define LL long long

template<typename elemType>
inline void Read(elemType& T) {
    elemType X = 0, w = 0; char ch = 0;
    while (!isdigit(ch)) { w |= ch == '-';ch = getchar(); }
    while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
    T = (w ? -X : X);
}

struct Graph {
    struct edge { int Next, to; };
    edge G[400010];
    int head[100010];
    int cnt;

    Graph() :cnt(2) {}
    void clear(int n) {
        cnt = 2;fill(head, head + n + 2, 0);
    }
    void add_edge(int u, int v) {
        G[cnt].to = v;
        G[cnt].Next = head[u];
        head[u] = cnt++;
    }
};

Graph G;
vector<int> cycle, s, path;
int dfn[100010], deep[100010];
bool mark[100010], findans;
int N, M, sq, Index;


void DFS(int u, int fa) {
    if (findans) return;
    path.push_back(u);
    dfn[u] = ++Index;
    int num = 0;
    bool flag = true;
    for (int i = G.head[u];i;i = G.G[i].Next) {
        if (findans) return;
        int v = G.G[i].to;
        if (!dfn[v] && v != fa) { deep[v] = deep[u] + 1;DFS(v, u); }
        else ++num;
        if (mark[v]) flag = false;
    }
    if (findans) return;
    if (num >= sq - 1) {
        for (int i = G.head[u];i;i = G.G[i].Next) {
            int v = G.G[i].to;
            if (dfn[v] && dfn[v] < dfn[u]) {
                if (deep[u] - deep[v] >= sq - 1) {
                    while (path.back() != v) {
                        cycle.push_back(path.back());
                        path.pop_back();
                    }
                    cycle.push_back(v);
                    findans = true;
                    return;
                }
            }
        }
    }
    if (flag) { s.push_back(u);mark[u] = true; }
    path.pop_back();
}

int main() {
    Read(N);Read(M);
    for (int i = 1;i <= M;++i) {
        int u, v;
        Read(u);Read(v);
        G.add_edge(u, v);
        G.add_edge(v, u);
    }
    sq = 1;
    while (sq * sq < N) ++sq;
    DFS(1, 0);
    if (findans) {
        printf("2\n");
        printf("%d\n", cycle.size());
        for (auto x : cycle)
            printf("%d ", x);
        printf("\n");
    }
    else {
        printf("1\n");
        for (int i = 0;i < sq;++i)
            printf("%d ", s[i]);
        printf("\n");
    }
    return 0;
}
posted @ 2021-03-13 13:41  AE酱  阅读(49)  评论(0编辑  收藏  举报