1142 Maximal Clique
A clique is a subset of vertices of an undirected graph such that every two distinct vertices in the clique are adjacent. A maximal clique is a clique that cannot be extended by including one more adjacent vertex. (Quoted from https://en.wikipedia.org/wiki/Clique_(graph_theory))
Now it is your job to judge if a given subset of vertices can form a maximal clique.
Input Specification:
Each input file contains one test case. For each case, the first line gives two positive integers Nv (≤ 200), the number of vertices in the graph, and Ne, the number of undirected edges. Then Ne lines follow, each gives a pair of vertices of an edge. The vertices are numbered from 1 to Nv.
After the graph, there is another positive integer M (≤ 100). Then M lines of query follow, each first gives a positive number K (≤ Nv), then followed by a sequence of K distinct vertices. All the numbers in a line are separated by a space.
Output Specification:
For each of the M queries, print in a line Yes if the given subset of vertices can form a maximal clique; or if it is a clique but not a maximal clique, print Not Maximal; or if it is not a clique at all, print Not a Clique.
Sample Input:
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
Sample Output:
Yes Yes Yes Yes Not Maximal Not a Clique
题意
在一个无向图中,如果一个顶点子集满足子集内的任意两个不同顶点之间都是相连的,那么这个顶点子集就被称为一个团。
如果一个团不能通过加入某个新的顶点来扩展成一个更大的团,那么该团就被称为最大团。
现在,你需要判断给定顶点子集能否构成一个最大团。
举个例子,下图中 [1,2,3,4] 就是该图的最大团,而 5 不在其中是因为 5 与 3 和 2 没有边。
思路
1.这题用邻接矩阵来存储每一条边。
2.每次询问时用数组 vers 去存储每个点值,并用 cnt 记录点数。然后先判判断该子集是否是团,如果是团再进一步判断是否为最大团。
1.判断是否是团,只需判断子集中每个点之间是否都存在边。
2.判断是否为最大团,需要先用一个数组 st 来标记子集中有哪些点,然后再遍历不是子集中的点,再去判断这些点是否和子集中的每个点都存在一条边,只要能找到一个这种点,就说明不是最大团。
3.根据判断结果,输出对应语句。
代码
#include<bits/stdc++.h> using namespace std; const int N = 210; int g[N][N]; int vers[N]; bool st[N]; int n, m; //判断是不是团 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() { cin >> n >> m; //记录每条边 for (int i = 0; i < m; i++) { 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 >> vers[i]; //输入子集 //判断是不是团 if (check_clique(cnt)) { //判断是不是最大团 if (check_maximum(cnt)) puts("Yes"); else puts("Not Maximal"); } else puts("Not a Clique"); } return 0; }