首先:
无向图的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
原文地址:https://www.cnblogs.com/scnucjh/p/12624151.html
时间: 2024-11-13 04:42:01