E
题意:比赛结束后因为自己没有调出来而感觉到不甘心,改出来之后忽然发现其实比赛的时候没有AC这题很正常的……
还有写哈希习惯性开那个接近2∗107的数字,发现空间挂了开了接近106的数字,却没有想过开107的数字,我在干嘛……
首先尝试找点集。类似拓扑排序,每次将度数小于k的点删掉,一直做。如果最后还有点剩余,就说明找到了点集。
如果找不到点集,就要尝试找团。再做一遍上面的操作,将限制改成k−1。
现在得到了一个新图,每个点的度数至少为k−1。接着判断度数为k−1的点是否在一个团内,判断的时候可以O(k2)(这里我写了哈希,假装它的复杂度是常数级别),如果判断出来就输出,如果判断不出来,将这个点以及其连边删去(这时候可能得到新的度数为k−1的点,丢入队列中操作)。
显然k≤2m−−−√,又由于每次操作会删去k−1条边,于是判断的操作只会做mk−1次,那么时间复杂度就是O(mk)的。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
vector<int>vv[maxn],uu[maxn],pp[maxn];
int degree[maxn];
int n,m,k;
queue<int>q;
int vis[maxn];
bool res[maxn];
int r;
void init()
{
r=0;
while(q.size())
q.pop();
for(int i=1;i<=n;i++)
vv[i].clear(),pp[i].clear(),degree[i]=0;
}
bool step1()
{
int cnt=n;
for(int i=1;i<=n;i++)
{
vis[i]=0;
if(degree[i]<k)
{
q.push(i);
}
}
cout<<endl;
while(q.size())
{
int u=q.front();
vis[u]=1;
cnt--;
q.pop();
if(degree[u]==k-1)
{
++r;
uu[r].clear();
uu[r].push_back(u);
pp[u].push_back(r);
for(int i=0;i<vv[u].size();i++)
{
if(!vis[vv[u][i]])
{
uu[r].push_back(vv[u][i]);
pp[vv[u][i]].push_back(r);
}
}
}
for(int i=0;i<vv[u].size();i++)
{
int v=vv[u][i];
if(vis[v]==0)
{
degree[v]--;
if(degree[v]==k-1)
q.push(v);
}
}
}
if(cnt>0)
{
cout<<1<<" "<<cnt<<"\n";
for(int i=1;i<=n;i++)
{
if(degree[i]>=k)
cout<<i<<" ";
}
cout<<"\n";
return 1;
}
return 0;
}
bool step2()
{
for(int i=1;i<=n;i++)
vis[i]=0;
for(int i=1;i<=r;i++)
res[i]=true;
for(int i=1;i<=n;i++)
{
if(pp[i].size()==0)
continue;
vis[i]=1;
for(int j=0;j<vv[i].size();j++)
vis[vv[i][j]]=1;
for(int j=0;j<pp[i].size();j++)
{
int tuan=pp[i][j];
if(res[tuan])
{
for(int k=0;k<uu[tuan].size();k++)
{
if(vis[uu[tuan][k]]==0)
{
res[tuan]=false;
break;
}
}
}
}
vis[i]=0;
for(int j=0;j<vv[i].size();j++)
vis[vv[i][j]]=0;
}
for(int i=1;i<=r;i++)
{
if(res[i])
{
cout<<2<<"\n";
for(int j=0;j<uu[i].size();j++)
cout<<uu[i][j]<<" ";
cout<<"\n";
return 1;
}
}
return 0;
}
void solve()
{
cin>>n>>m>>k;
init();
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
vv[x].push_back(y);
vv[y].push_back(x);
degree[x]++;
degree[y]++;
}
if(k*(k-1)>2*m)
{
cout<<-1<<"\n";
return;
}
if(step1())
{
return ;
}
if(step2())
{
return ;
}
cout<<-1<<"\n";
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int _=1;
cin>>_;
while(_--)
solve();
}