对于图建立dfs树,这样只存在树边和B边,不会存在横叉边,这也是tarjan算法的思想
建立dfs树后,我们发现任意一条B边都会生成一个环,且所有b边就是所有环
我们进行dfs栈的建立,找到如果存在满足条件的环,那就直接输出
如果不存在,我们证明肯定存在满足条件的独立集。因为根据鸽巢定理,每个点一定不会有大于lim-2条回边,这是因为一旦有lim-1条,则肯定能联通lim个点,那么就存在满足条件的环
既然发现这个,我们就可以从深度最低的开始打tag,不断往回,一定能找到答案。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=5e5+10; int h[N],ne[N],e[N],idx; void add(int a,int b){ e[idx]=b,ne[idx]=h[a],h[a]=idx++; } int n,m,lim; stack<int> q; int depth[N]; int tag[N]; void dfs(int u,int now,int fa){ depth[u]=now; q.push(u); int i; for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa) continue; if(!depth[j]){ dfs(j,now+1,u); } else{ if(depth[u]-depth[j]+1>=lim){ cout<<2<<endl; cout<<depth[u]-depth[j]+1<<endl; for(i=depth[u]-depth[j]+1;i>=1;i--){ int t=q.top(); q.pop(); cout<<t<<" "; } cout<<endl; exit(0); } } } if(!tag[u]){ for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; tag[j]=1; } } q.pop(); } int main(){ int k; ios::sync_with_stdio(false); cin>>n>>m; memset(h,-1,sizeof h); lim=sqrt(n); if(lim*lim<n) lim++; while(m--){ int a,b; cin>>a>>b; add(a,b); add(b,a); } depth[1]=1; dfs(1,1,-1); cout<<1<<endl; int cnt=1; while(lim){ while(tag[cnt]) cnt++; cout<<cnt<<" "; cnt++; lim--; } return 0; }