Ehab's Last Theorem (补)(dfs树+鸽巢原理)

题意:

给你n个点和m条边,让你找一个大于等于√n的环或找一个点数等于√n的独立集
链接:https://codeforces.com/contest/1325/problem/F

思路:根据dfs树的原理,相同深度的点之间必定没有边相连,我们将点的深度从

0到√n⌉-1进行划分,根据鸽巢原理,必定存在一个深度满足这个深度的点的数量

大于等于√n

代码:

#include <bits/stdc++.h>
#include<windows.h>
using namespace std;
typedef long long ll;
const int MAXN=2e5+5;
const int INF=0x3f3f3f3f3f3f3f;
const int mod=998244353;
int head[MAXN],tot,limit;
struct node
{
    int to,nxt;
} e[MAXN<<2];
void add(int x,int y)
{
    e[tot].to=y;
    e[tot].nxt=head[x];
    head[x]=tot++;
}
void add_edge(int x,int y)
{
    add(x,y);
    add(y,x);
}
int fa[MAXN],num[MAXN],dep[MAXN];
void dfs(int u)
{
    num[dep[u]%(limit-1)]++;
    for(int i=head[u]; ~i; i=e[i].nxt)
    {
        int v=e[i].to;
        if(v==fa[u])
            continue;
        if(dep[v]==-1)
        {
            dep[v]=dep[u]+1;
            fa[v]=u;
            dfs(v);
        }
        else
        {
            if(dep[u]-dep[v]+1>=limit)
            {
                cout<<"2"<<endl;
                cout<<dep[u]-dep[v]+1<<endl;
                for(int i=u; i!=v; i=fa[i])
                    cout<<i<<" ";
                cout<<v<<endl;
                exit(0);
            }
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,m;
    cin>>n>>m;
    memset(head,-1,sizeof(head));
    memset(dep,-1,sizeof(dep));
    for(int i=1; i<=m; i++)
    {
        int u,v;
        cin>>u>>v;
        add_edge(u,v);
    }
    limit=(int)ceil(sqrt(n));
    dep[1]=0;
    dfs(1);
    int temp=*max_element(num,num+limit-1);
    int cnt=0;
    cout<<"1"<<endl;
    for(int i=1; i<=n; i++)
    {
        if(num[dep[i]%(limit-1)]==temp)
            cout<<i<<" ",cnt++;
        if(cnt==limit)
            break;
    }
    return 0;
}

 

posted @ 2020-03-25 12:39  grass_lin  阅读(247)  评论(0编辑  收藏  举报