【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\n%d\n",dep[u]-dep[v]+1);
                for(int i=dep[v]-1;i<dep[u];i++)
                    printf("%d ",vec[i]);
                printf("\n");
                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\n");
    for(int i=0;i<lim;i++)
        printf("%d ",ans[i]);
    printf("\n");
    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\n%d\n",dep[u]-dep[v]+1);
                for(int i=dep[v]-1;i<dep[u];i++)
                    printf("%d ",vec[i]);
                printf("\n");
                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\n");
    for(int i=0;i<(k+1)/2;i++)
        printf("%d ",ans[i]);
    printf("\n");
    return 0;
}
/*
*/
posted @ 2020-07-13 08:47  Valk3  阅读(100)  评论(0编辑  收藏  举报