晚上这题写了一半感觉不太对就去写F了,结果F也写了个假贪心,虽然靠前四题的手速还是上了分小号也紫了,不过下场只能div1那么又要掉回div2了。
这题事实上巨水。只要能想到一条边占用两个点,这两个点是一次性被占用掉的,所以跟什么dfs顺序啥的都没关系,只有讨论点的时候要考虑dfs树的相邻节点属于不同集合。但这里只要把点当成消耗品去加边就行了,因为一个点最多连一条边,不连白不连。
于是就一直尝试加边,保证答案集合中的边没有共享端点的。
如果边数不到n输出点集,点集按道理是要dfs去判断哪个点集大的,但是由于有3*n个点,而且边不足n条,也就是说剩下的点之间是没有边的且这个点数=3*n-2*边数,所以这个独立点数直接就>n,直接输出就行了。
#include<bits/stdc++.h>
#define maxl 500010
using namespace std;
int n,m,flag;
int ans[maxl];
bool vis[maxl];
inline void prework()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=3*n;i++)
vis[i]=false;
ans[0]=0;
int u,v;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
if(!vis[u] && !vis[v])
{
vis[u]=vis[v]=true;
ans[++ans[0]]=i;
}
}
if(ans[0]>=n)
{
flag=1;
return;
}
flag=2;
ans[0]=0;
for(int i=1;i<=3*n;i++)
if(!vis[i])
ans[++ans[0]]=i;;
}
inline void mainwork(){}
inline void print()
{
if(flag==1)
puts("Matching");
else
puts("IndSet");
for(int i=1;i<=n;i++)
printf("%d%c",ans[i],(i==n)?'\n':' ');
}
int main()
{
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}