【题解】【AcWing】1635. 最大团

306 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

1635. 最大团

原题传送:AcWing 1635. 最大团

在一个无向图中,如果一个顶点子集满足子集内的任意两个不同顶点之间都是相连的,那么这个顶点子集就被称为一个团。

如果一个团不能通过加入某个新的顶点来扩展成一个更大的团,那么该团就被称为最大团。

现在,你需要判断给定顶点子集能否构成一个最大团。

输入格式

第一行包含两个整数 NvN_vNeN_e ,分别表示无向图中点和边的数量。

接下来 NeN_e 行,每行包含两个整数 a,ba,b ,表示点 aa 和点 bb 之间存在一条边。

所有点的编号从 11NvN_v

再一行,包含整数 MM ,表示询问次数。

接下来 MM 行,每行描述一个询问顶点子集,首先包含一个整数 KK ,表示子集包含点的数量,然后包含 KK 个整数,表示 KK 个不同顶点的编号。

一行中所有数字之间用一个空格隔开。

输出格式

每组询问在一行中输出一个结论。

如果给定子集是最大团,则输出Yes,如果是一个团,但不是最大团,则输出Not Maximal,如果根本不是团,则输出Not a Clique

数据范围

1Nv2001 \le N_v \le 200 , 1NeNv(Nv1)21 \le N_e \le \frac{N_v(N_v-1)}{2} , 1M1001 \le M \le 100 , 1KNv1 \le K \le N_v

输入样例:

8 10
5 6
7 8
6 4
3 6
4 5
2 3
8 2
2 7
5 3
3 4
6
4 5 4 3 6
3 2 8 7
2 2 3
1 1
3 4 3 6
3 3 2 1

输出样例:

Yes
Yes
Yes
Yes
Not Maximal
Not a Clique

思路:

建立图,遍历查询的所有点对,若存在无边的点对,则不是团。如果是团,遍历集合外的点能否和集合内的所有点有边,若有边,则当前团不是最大团。

题解:

#include <bits/stdc++.h>

using namespace std;

const int N = 210;

int n, m;
bool g[N][N], st[N];
int vers[N];

bool check_clique(int cnt)
{
	for(int i = 0; i < cnt; i++)
		for(int j = 0; j < i; j++)
			if(!g[vers[i]][vers[j]])
				return false;
	return true;
}

bool check_maximum(int cnt)
{
	memset(st, 0, sizeof st);
	for(int i = 0; i < cnt; i++)
		st[vers[i]] = true;

	for(int i = 1; i <= n; i++)
	{
		if(!st[i])
		{
			bool success = true;
			for(int j = 0; j < cnt; j++)
			{
				if (!g[i][vers[j]])
				{
                    success = false;
                    break;
                }
			}
			if(success) return false;
		}
	}
	return true;
}

int main()
{
	scanf("%d%d", &n, &m);
		
	for(int i = 0; i < m; i++)
	{
		int a, b;
		scanf("%d%d", &a, &b);
		g[a][b] = g[b][a] = true;
	}
	
	int k;
	scanf("%d", &k);
	
	while(k--)
	{
		int cnt;
		scanf("%d", &cnt);
		for(int i = 0; i < cnt; i++)
			scanf("%d", &vers[i]);
		if(check_clique(cnt))
		{
			if(check_maximum(cnt))
				printf("Yes\n");
			else
				printf("Not Maximal\n");
		}
		else
			printf("Not a Clique\n");
	}
	
	return 0;
}