• F. Ehab's Last Theorem dfs树!!!


    F. Ehab's Last Theorem

    题目大意:

    给你一个图,构造一个序列,这个序列有两种构造方法,任选其一构造即可。

    • 找到一个独立集,独立集包含 (left lceil sqrt[]{n} ight ceil) 个点。
    • 找到一个简单环,这个环上的点至少 (left lceil sqrt[]{n} ight ceil) 个,且按照环的顺序输出序列。

    如果是第一种,则第一行先输出1,第二行输出这个序列,如果是第二种,则先输出2,再输出序列。

    题解:

    首先建一棵 (dfs) 树, (dfs) 树有一个性质就是:

    每一个节点只会连向它的后代节点,或者说每一个回边都是后代连向他的祖先节点
    (dfs) 树构建完之后,对于一个节点,它的子节点之间是不会有边相连的。

    知道这个性质之后,我们可以尝试去找简单环,这个在一棵树上还是很好找的。

    • 对这棵树进行 (dfs) 如果出现回边,那就说明构成了一个简单环,就判断这个简单环的节点数是不是大于(left lceil sqrt[]{n} ight ceil) ,大于则可以之间输出答案。

    • 如果没有找到满足条件的简单环,那肯定可以找到一个满足条件的独立集,这是为什么呢?

      因为没有两个点之间的深度大于等于 (left lceil sqrt[]{n} ight ceil - 1) 的环,所以剩下的两个节点之间的深度肯定是小于等于 (left lceil sqrt[]{n} ight ceil - 2) 的,所以我们选完一个节点之后,最多会删除 (left lceil sqrt[]{n} ight ceil - 1) 个点 ,

      $ left lceil frac{n}{ left lceil sqrt[]{n} ight ceil - 1 } ight ceil $ >= (left lceil sqrt[]{n} ight ceil),所以肯定可以找到满足条件的独立集。

      接下来解释一下为什么是最多呢?因为对于一个节点来说,它的子节点之间肯定不会有边相连,所以如果我选中的值往上走走不了(left lceil sqrt[]{n} ight ceil) ,则不需要删(left lceil sqrt[]{n} ight ceil - 1) 这么多的节点数。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=4e5+10;
    int head[maxn],cnt;
    struct node{
        int v,nxt;
        node(int v=0,int nxt=0):v(v),nxt(nxt){}
    }e[maxn];
    void add(int u,int v){
        e[++cnt]=node(v,head[u]);
        head[u]=cnt;
        e[++cnt]=node(u,head[v]);
        head[v]=cnt;
    }
    int n,m,tot=0;
    int dep[maxn],fa[maxn],ver[maxn];
    void dfs(int u){
        ver[++tot]=u;
        dep[u]=dep[fa[u]]+1;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].v;
            if(v==fa[u]) continue;
            if(!dep[v]){
                fa[v]=u;
                dfs(v);
            }
            else{
                long long  l=dep[u]-dep[v]+1;
                if(l*l>=n){
                    printf("2
    %d
    ",l);
                    int x=u;
                    while(x!=v){
                        printf("%d ",x);
                        x=fa[x];
                    }
                    printf("%d
    ",v);
                    exit(0);
                }
            }
        }
    }
    bool vis[maxn];
    int main(){
        cnt=0;
        scanf("%d%d",&n,&m);
        for(int i=1,u,v;i<=m;i++){
            scanf("%d%d",&u,&v);
            add(u,v);
        }
        dfs(1);
        int l=1;
        for(;l*l<n;l++);
        int cur=l;
        printf("1
    ");
        for(int i=n;i>=1;i--){
            int u=ver[i];
            if(vis[u]) continue;
            l--;
            printf("%d%c",u,l?' ':'
    ');
            if(!l) break;
            for(int i=1;i<=cur-1;i++){
                vis[u]=1;
                u=fa[u];
            }
        }
        return 0;
    }
    
  • 相关阅读:
    jquery对同级的td做radio限制
    "javascript:void(0)"用法
    SQL 插入查询的最大ID 号 进行批量
    Java数字、货币值和百分数等的格式化处理
    PHP 注意问题
    Android Fragment真正意义上的onResume和onPause
    Android_CodeWiki_03
    Android_CodeWiki_02
    Android_CodeWiki_01
    Android 启动APP黑屏解决方案
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/13394009.html
Copyright © 2020-2023  润新知