最大团 题型:图论

107 阅读3分钟

1635. 最大团 - AcWing题库

题意解析

团:子集内任意两个顶点都有边相连。

非团:有顶点但是没有边相连。

最大团:是团且不能再加入其他顶点使其扩展为更大的团。

非最大团:是团且可以加入其他顶点使其扩展为更大的团。

判断是否是最大团

首先判断子集是否是一个团。如果一个子集内任意两点之间都有边相连,那么就说该子集是一个团。

然后判断该团是否是一个最大团。如果存在一个不在该团内的点且该点与该团内任意顶点都有一条边,那么就说这个团不是最大团。

样例模拟

这是题目提供的图: image.png

第一个询问

子集为{5,3,4,6},该子集内任意两点之间存在一条边,是一个团。且不存在团外一点与团内所有点都存在一条边,因此该团是一个最大团:

输出"yes": image.png

第二个询问

子集为{2,8,7},该子集内任意两点之间存在一条边,是一个团,且不存在团外一点与团内所有点都存在一条边,因此该团是一个最大团:

输出"yes": image.png

第三个询问

子集为{2,3},该子集内任意两点之间存在一条边,是一个团,且不存在团外一点与团内所有点都存在一条边,因此该团是一个最大团:

输出"yes": image.png

第四个询问

子集为{1},子集内任意两点之间有一条边(自己与自己连),是团。

且没有团外任意一点与团内所有点存在一条边,是最大团。

输出"yes":

image.png

第五个询问:

子集为{4,3,6},该子集满足子集内任意两顶点之间存在一条边,因此是一个团。

另外我们可以发现团外一点5与该团内任意顶点之间都有一条边,因此该团不是一个最大团。

输出"Not Maximal":

image.png

第六个询问:

子集为{1,2,3},因为该子集内不满足任意两点之间存在一条边(3到1没有边),所以该子集不是一个团。

输出"Not a Clique": image.png

code

#include<bits/stdc++.h>
using namespace std;
int n, m,k;
const int N = 210;
int g[N][N];
bool st[N];
int ver[N];

//判断是否是一个团
//方法:判断团内任意两个定点之间是否都存在一条边
bool is_clique(int cnt) {
	for (int i = 0; i < cnt; i++)
		for (int j = 0; j < i; j++)
			if (!g[ver[i]][ver[j]])return false;
	return true;
}


//判断是否为一个最大团
//方法:判断团外是否存在一个点与团内任意顶点存在一条边
bool is_max_clique(int cnt)
{
	memset(st,false,sizeof st);  //初始化每个点为没走过

	//看看能否加入一个新边
	for (int i = 0; i < cnt; i++)st[ver[i]] = true;  //每个顶点都初始化为true

	//枚举每一个点
	for (int i = 1; i <= n; i++)
	{
		bool res = true;
		if (!st[i])  //没有被访问过的话
		{
		    res = true;  
			for (int j = 0; j < cnt; j++)
			{
				if (!g[i][ver[j]])   //这个点与几何没有关联,这个点就不能加入团
				{
					res = false;    //那么这个团就是一个最大团
					break;
				}
			}
			if (res)return false;
		}
	}
}
int main()
{
	cin >> n >> m;
	while (m--)
	{
		int a, b;
		cin >> a >> b;
		g[a][b] = g[b][a] = true;
	}
	int k;
	cin >> k;
	while (k--)
	{
		int cnt;
		cin >> cnt;
		for (int i = 0; i < cnt; i++) cin >> ver[i];
		if (is_clique(cnt))
		{
			if (is_max_clique(cnt)) puts("Yes");
			else puts("Not Maximal");
		}
		else puts("Not a Clique");
	}


	return 0;
}

image.png