码迷,mamicode.com
首页 > 其他好文 > 详细

CF 1325F - Ehab's Last Theorem

时间:2020-04-03 09:15:46      阅读:116      评论:0      收藏:0      [点我收藏+]

标签:its   last   end   syn   out   ack   pre   大于   space   

首先:

无向图的dfs树无横边

这很显然,因为若有u->v 为横边,那么v早就从这条边过来找u了...矛盾

\(k = ceil( \sqrt{n} )\)

接下来跑dfs树,如果有回边使得环大于等于k,就输出环。

否则,说明一个问题:所有点的回边的数量都小于k(不然一定能找到环了,鸽巢原理~)

于是,可以不停自底向上地选取点为独立集点,同时把它的领边都标记为不能取为独立集。

结果一定至少有k个独立集点。

为什么? 因为前面说了,所有点的回边的数量都小于k,这样取点,每去一次点,最多标记k-1个点为非独立集。

代码中,flag[i] = 1 表示\(i\)已经标为不是独立集点。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N = 1e5+5;
bool flag[N];
int fa[N], dep[N];

int n,m,k;
vector<int> G[N];

void dfs(int x,int f,int d) {
    dep[x] = d;
    fa[x] = f;
    for(auto y:G[x]) {
        if(dep[y]==0)
            dfs(y,x,d+1);
        if(dep[x]-dep[y]+1>=k) {
            cout<<2<<endl;
            cout<<dep[x]-dep[y]+1<<endl;
            cout<<y<<" ";
            int z = x;
            while(z!=y) {
                cout<<z<<" ";
                z = fa[z];
            }
            exit(0);
        }
    }
    if(!flag[x])
        for(auto y:G[x]) {
            flag[y] = 1;
        } 
}

int main() {
    ios::sync_with_stdio(0);
    cin>>n>>m;
    while(k*k<n) k++;

    for(int i=0,a,b;i<m;i++) {
        cin>>a>>b;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    dfs(1,0,1);
    cout<<1<<endl;
    for(int i=1; k; i++) {
        if(flag[i]) continue;
        cout<<i<<" ";
        k--;
    }
    return 0;
}

CF 1325F - Ehab's Last Theorem

标签:its   last   end   syn   out   ack   pre   大于   space   

原文地址:https://www.cnblogs.com/scnucjh/p/12624151.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!