1635. 最大团
原题传送:AcWing 1635. 最大团
在一个无向图中,如果一个顶点子集满足子集内的任意两个不同顶点之间都是相连的,那么这个顶点子集就被称为一个团。
如果一个团不能通过加入某个新的顶点来扩展成一个更大的团,那么该团就被称为最大团。
现在,你需要判断给定顶点子集能否构成一个最大团。
输入格式
第一行包含两个整数 N v N_v Nv 和 N e N_e Ne ,分别表示无向图中点和边的数量。
接下来 N e N_e Ne 行,每行包含两个整数 a , b a,b a,b ,表示点 a a a 和点 b b b 之间存在一条边。
所有点的编号从 1 1 1 到 N v N_v Nv 。
再一行,包含整数 M M M ,表示询问次数。
接下来 M M M 行,每行描述一个询问顶点子集,首先包含一个整数 K K K ,表示子集包含点的数量,然后包含 K K K 个整数,表示 K K K 个不同顶点的编号。
一行中所有数字之间用一个空格隔开。
输出格式
每组询问在一行中输出一个结论。
如果给定子集是最大团,则输出Yes
,如果是一个团,但不是最大团,则输出Not Maximal
,如果根本不是团,则输出Not a Clique
。
数据范围
1
≤
N
v
≤
200
1 \le N_v \le 200
1≤Nv≤200 ,
1
≤
N
e
≤
N
v
(
N
v
−
1
)
2
1 \le N_e \le \frac{N_v(N_v-1)}{2}
1≤Ne≤2Nv(Nv−1) ,
1
≤
M
≤
100
1 \le M \le 100
1≤M≤100 ,
1
≤
K
≤
N
v
1 \le K \le N_v
1≤K≤Nv
输入样例:
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;
}