https://codeforces.com/contest/1439/problem/B
unordered_map,set都过不了,学习了jiangly的代码写了binary_search(e[x].begin(),e[x].end(),y)就过了,离谱
首先要有解那么就必须k*(k-1)<=2m,否则度数凑不出来大小为k的团,更凑不出每个点都>=k的子集
然后不停得把那些du<k的删去,如果要删掉一个du为k-1的,那么直接把他连向的点全拿出来看是不是一个团,用二分去找两两之间是否有边
由于k<=sqrt(m),那么整个图最多m/k个度>=k的点,然后每一次枚举只会枚举k次,然后判断是k^2logk,总复杂度就是k^3logk=msqrt(m)logk,用hash可以优化掉log,但是unordered_mapset太慢了还不如二分
如果最后有点没有被删掉,那么就说明剩下的点每个点的度数都是>=k的,说明存在子集
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
typedef long long ll;
const int maxl=1e5+10;
int n,m,k,ans;
int du[maxl];
vector<int> cliq,subs;
vector<int> e[maxl];
//unordered_set<int> ste[maxl];
unordered_map<int,bool> mp[maxl];
bool vis[maxl],del[maxl];
inline void prework()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
{
e[i].clear();
//ste[i].clear();
vis[i]=del[i]=false;du[i]=0;
}
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
//ste[u].insert(v);
du[u]++;
//ste[v].insert(u);
du[v]++;
e[u].pb(v);e[v].pb(u);
}
for(int i=1;i<=n;i++)
sort(e[i].begin(),e[i].end());
}
inline void mainwork()
{
if(1ll*k*(k-1)>2*m)
{
ans=-1;
return;
}
queue<int> q;
for(int i=1;i<=n;i++)
if(du[i]<k)
vis[i]=true,q.push(i);
cliq.clear();
while(!q.empty())
{
int u=q.front();q.pop();
if(du[u]==k-1)
{
cliq.pb(u);
for(int v:e[u])
if(!del[v])
cliq.pb(v);
bool flag=true;
for(int x:cliq)
for(int y:cliq)
{
if(x==y)
break;
if(!binary_search(e[x].begin(),e[x].end(),y))
flag=false;
}
if(flag)
{
ans=2;
return;
}
cliq.clear();
}
del[u]=true;
for(int v:e[u])
{
--du[v];
//ste[v].erase(u);
if(du[v]<k && !vis[v])
{
vis[v]=true;
q.push(v);
}
}
}
subs.clear();ans=-1;
for(int i=1;i<=n;i++)
if(!vis[i])
subs.pb(i),ans=1;
}
inline void print()
{
if(ans<0)
puts("-1");
else if(ans==1)
{
int l=subs.size();printf("1 %d\n",l);
for(int i=0;i<l;i++)
printf("%d%c",subs[i]," \n"[i==l-1]);
}
else
{
puts("2");
for(int i=0;i<k;i++)
printf("%d%c",cliq[i]," \n"[i==k-1]);
return;
}
}
int main()
{
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}