先将所有度数小于d的点推入队列,然后把这些点相连的点度数-1,如果一个没入队过的点度数-1后度数小于d,那么把这个点入队。
然后找没入队过的点形成的最大连通块就是答案。
#include <bits/stdc++.h>
using namespace std;
#define N 210000
int n,m,d,tot,pos;
int head[N],nex[N<<1],to[N<<1];
int vis[N],fa[N],size[N],du[N];
queue<int>que;
void add(int x,int y)
{
tot++;
nex[tot]=head[x];head[x]=tot;
to[tot]=y;
}
int find(int x){return x==fa[x] ? x:fa[x]=find(fa[x]);}
int main()
{
//freopen("tt.in","r",stdin);
scanf("%d%d%d",&n,&m,&d);
for(int i=1,x,y;i<=m;i++)
{
scanf("%d%d",&x,&y);
add(x,y);add(y,x);
du[x]++;du[y]++;
}
for(int i=1;i<=n;i++)
if(du[i]<d)que.push(i),vis[i]=1;
while(!que.empty())
{
int t=que.front();que.pop();
for(int i=head[t];i;i=nex[i])
if(!vis[to[i]]&&--du[to[i]]<d)
vis[to[i]]=1,que.push(to[i]);
}
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=n;i++)
if(!vis[i])
for(int j=head[i];j;j=nex[j])
if(!vis[to[j]])
{
if(find(i)!=find(to[j]))
fa[find(i)]=find(to[j]);
}
for(int i=1;i<=n;i++)
if(!vis[i])size[find(i)]++;
for(int i=1;i<=n;i++)
if(!vis[i]&&size[find(i)]>size[pos])
pos=find(i);
if(!pos)return puts("NIE"),0;
printf("%d\n",size[pos]);
for(int i=1;i<=n;i++)
if(find(i)==pos)
printf("%d ",i);
return 0;
}