Codeforces 1325 F Ehabs Last Theorem —— dfs樹

This way

題意:

給你一張圖,你有兩種選擇:
1.找到裏面一個大小爲n\lceil\sqrt{n}\rceil的獨立集
2.找到裏面一個長度大於等於n\lceil\sqrt{n}\rceil的簡單環

題解:

很久沒寫程序了,都有點生疏。
那麼這道題一開始如果當成一張圖去想的話我覺得很難想,但是衆所周知連通圖圖其實可以看成在一棵生成樹上加邊。那麼選擇2就很簡單了:
對於找到的生成樹上深度相差這麼多的兩個連通的點就是所要求的簡單環
如果沒有呢,那麼我們將每個點的深度取模n1\lceil\sqrt{n}\rceil-1,那麼其中至少有一個深度的點的數量>=n\lceil\sqrt{n}\rceil。這就是鴿巢原理。

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int num[N],cnt;
struct node{
    int to,next;
}e[N*2];
int tot,head[N],dep[N],mod;
void add(int x,int y){
    e[tot].to=y;
    e[tot].next=head[x];
    head[x]=tot++;
}
stack<int>st;
void dfs(int x,int fa){
    dep[x]=dep[fa]+1;
    num[dep[x]%mod]++;
    st.push(x);
    for(int i=head[x];~i;i=e[i].next){
        int ne=e[i].to;
        if(ne==fa)continue;
        if(dep[ne]||ne==1){
            if(dep[x]-dep[ne]+1>=cnt){
                printf("2\n%d\n",dep[x]-dep[ne]+1);
                while(1){
                    printf("%d\n",st.top());
                    if(st.top()==ne)break;
                    st.pop();
                }
                exit(0);
            }
            continue;
        }
        dfs(ne,x);
    }
    st.pop();
}
int main()
{
    memset(head,-1,sizeof(head));
    int n,m,x,y;
    scanf("%d%d",&n,&m);
    mod=sqrt(n);
    if(mod*mod!=n)mod++;
    cnt=mod;
    mod--;
    for(int i=1;i<=m;i++)
        scanf("%d%d",&x,&y),add(x,y),add(y,x);
    dep[0]=-1;
    dfs(1,0);
    int ans;
    for(int i=0;i<mod;i++){
        if(num[i]>=cnt){
            printf("1\n");
            for(int j=1;j<=n;j++){
                if(dep[j]%mod==i)
                    printf("%d\n",j),cnt--;
                if(!cnt)
                    exit(0);
            }
        }
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章