zoukankan      html  css  js  c++  java
  • 【Codeforces-1325 F】DFS树 求简单环 独立点集

    F. Ehab's Last Theorem

    题意

    给出一个 n 个顶点,m 条无向边的连通图,现在你可以选择以下两个问题中的一个问题解决。

    1. 找到一个大小为 (⌈ sqrt{n} ⌉)的独立点集
    2. 找到一个大小最少为为(⌈ sqrt{n} ⌉) 的简单环

    思路

    本题需要学习DFS树

    在 DFS 的时候如果遇到回边,判断这个环中的点是不是满足条件,满足直接输出。

    给出一个结论:如果不存在满足条件的简单环,那么一定存在满足条件的独立点集。

    证明:

    如果一个点有超过 (sqrt{n} - 2) 条父边(就是从其祖先节点连向这个点的边),那么就肯定有一个最少为 $ sqrt{n} $的环。

    所以现在每个点最多有 (sqrt{n} - 2) 条父边,那么加上它的一条向下的子边,最多会影响 (sqrt{n} - 1) 个点不能被选择,那么就可以选出 (sqrt{n}) 大小的独立集。

    代码

    #include<bits/stdc++.h>
    #define pb push_back
    const int N=1e6+10;
    const int inf=0x3f3f3f3f;
    typedef long long ll;
    typedef unsigned long long ull;
    using namespace std;
    
    vector<int>g[N],ans,vec;
    int n,m,lim;
    int dep[N],vis[N];
    void dfs(int u)
    {
        vec.pb(u);
        dep[u]=vec.size();
        for(int v:g[u])
        {
            if(!dep[v])
                dfs(v);
            else
            {
                if(dep[u]-dep[v]+1>=lim)//找到环
                {
                    printf("2
    %d
    ",dep[u]-dep[v]+1);
                    for(int i=dep[v]-1;i<dep[u];i++)
                        printf("%d ",vec[i]);
                    printf("
    ");
                    exit(0);
                }
            }
        }
        if(!vis[u])//vis为1表示这个点被影响过了
        {
            ans.pb(u);
            for(int v:g[u])
                vis[v]=1;
        }
        vec.pop_back();
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        lim=(int)sqrt(n-1)+1;
        for(int i=1,u,v;i<=m;i++)
        {
            scanf("%d%d",&u,&v);
            g[u].pb(v);
            g[v].pb(u);
        }
        dfs(1);
        printf("1
    ");
        for(int i=0;i<lim;i++)
            printf("%d ",ans[i]);
        printf("
    ");
        return 0;
    }
    

    还有一道题与此类似:

    D. Ehab's Last Corollary

    题意要求是恰好 (⌈ frac{k}{2} ⌉) 个独立点,或者最多 $ k $ 个点的简单环。

    假如不存在满足条件的环,那么环的大小最小为 (k+1) ,那么在换上隔一个点取一个就可以得到独立点集。

    代码 (与上类似)

    #include<bits/stdc++.h>
    #define pb push_back
    const int N=1e6+10;
    const int inf=0x3f3f3f3f;
    typedef long long ll;
    typedef unsigned long long ull;
    using namespace std;
    
    vector<int>g[N],ans,vec;
    int n,m,k;
    int dep[N],vis[N];
    void dfs(int u,int fa)
    {
        vec.pb(u);
        dep[u]=vec.size();
        for(int v:g[u])
        {
            if(v==fa) continue;
            if(!dep[v])
                dfs(v,u);
            else
            {
                if(dep[u]-dep[v]+1>2&&dep[u]-dep[v]+1<=k)
                {
                    printf("2
    %d
    ",dep[u]-dep[v]+1);
                    for(int i=dep[v]-1;i<dep[u];i++)
                        printf("%d ",vec[i]);
                    printf("
    ");
                    exit(0);
                }
            }
        }
        if(!vis[u])
        {
            ans.pb(u);
            for(int v:g[u])
                vis[v]=1;
        }
        vec.pop_back();
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1,u,v;i<=m;i++)
        {
            scanf("%d%d",&u,&v);
            g[u].pb(v);
            g[v].pb(u);
        }
        dfs(1,1);
        printf("1
    ");
        for(int i=0;i<(k+1)/2;i++)
            printf("%d ",ans[i]);
        printf("
    ");
        return 0;
    }
    /*
    */
    
  • 相关阅读:
    山东理工大学ACM平台题答案关于C语言 1137 C/C++经典程序训练7---求某个范围内的所有素数
    又遇BUG-ORA-01148:数据文件忽然变为recover状态
    poj 1191 棋盘分割 动态规划
    libevent的使用方法--回显服务器的简单实例
    java.lang.OutOfMemory总结分析
    山东理工大学ACM平台题答案关于C语言 1580 闰年
    SAE搭建WordPress教程 免费建WordPress博客站
    编译小结(6)认识Automake
    PHP再学习1——cURL表单提交、HTTP请求和响应分析
    新手一步一步OpenCV+Win7+Visual Studio 2013环境配置
  • 原文地址:https://www.cnblogs.com/valk3/p/13291452.html
Copyright © 2011-2022 走看看