题目描述:
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.
输入格式:
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.
输出格式:
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.
输入样例:
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
题意:
给出一个无向图的顶点数Nv和边数Ne,并给出对应的联结边,结点编号为1-Nv。再给出查询数M,判断M个序列是否为Maximal Clique。
在Clique中,所有的结点两两都是连通的。
Maximal Clique除了满足是Clique的要求,还要满足不可被扩展的条件,即在1-Nv的结点中,没有出现在这个序列中的结点,不可能与该序列中的每一个结点都两两连通。
思路:
首先判断一个序列是否是Clique,即序列中的每个结点是否两两连通,这里我使用了邻接矩阵的方式,因为这样可以直接判断两个点有没有连通,而不用循环去查找一个数。
判断一个Clique是否是Maximum Clique,我采用的方法是判断是否有不是这个序列的结点能够和这个序列中的每个结点都两两连通。
详见代码~
参考代码:
#include <stdio.h>
int Nv, Ne, m; //顶点数,无向边数,查询数量
const int maxv = 210;
bool G[maxv][maxv] = {false};
int checkClique(int seq[], int k){
bool inSeq[Nv+1] = {false};
for(int i = 0; i < k; i++){
int st = seq[i];
inSeq[st] = true;
for(int j = i + 1; j < k; j++){
int ed = seq[j];
if(!G[st][ed]) return 0; //Not a Clique
}
}
//寻找是否有其他结点可以和这个Clique组成一个更大的Clique
for(int i = 1; i <= Nv; i++){
if(inSeq[i] == false){
int cnt = 0; //有几对联结
for(int j = 0; j < k; j++){
int now = seq[j];
if(G[i][now]) cnt++; //找到这两者的联结
}
if(cnt == k) return 2; //Not Maximal
}
}
return 1; //Yes
}
int main(){
scanf("%d%d", &Nv, &Ne);
for(int i = 0; i < Ne; i++){
int st, ed;
scanf("%d%d", &st, &ed);
G[st][ed] = true;
G[ed][st] = true;
}
scanf("%d", &m);
for(int i = 0; i < m; i++){
int k; //每次查询的结点数
scanf("%d", &k);
int seq[k];
for(int j = 0; j < k; j++){
scanf("%d", &seq[j]);
}
int flag = checkClique(seq, k);
if(flag == 0){
printf("Not a Clique\n");
}else if(flag == 1){
printf("Yes\n");
}else{
printf("Not Maximal\n");
}
}
return 0;
}