A1142
Description:
clique:团,一个无向图的完全子图;
Maximal Clique:极大团,如果一个团不被其他任一团所包含,即它不是其他任一团的真子集,则称该图为图G的极大团;
给出一个无向图,判断所给序列是不是团、极大团;
思路:
- 拿到题思路十分凌乱,经柳神点拨,可以先确定是不是团,然后根据团外的点判断是不是最大团;
- 判断是不是团即判断是不是完全图,对于团内的任意两点确定之间是否存在边相连;
- 判断是不是最大,即遍历团外的所有点,若存在一点使得团内所有点与之都有边相连,则当前团非最大团;
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 205;
bool mp[maxn][maxn]; //存储无向边
int nv, ne, k, m;
vector<int>qur; //存储将要判断的序列
bool flag; //用于标志当前还是否为团,每次询问更新
void init(){
qur.clear(); //清空判断序列
flag = true; //初始化当前为团
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("1.txt", "r", stdin);
#endif // ONLINE_JUDGE
memset(mp, false, sizeof(false));
scanf("%d%d", &nv, &ne); //图的节点数及边数
int u, v;
set<int>all; //存放所有节点
while(ne--){
scanf("%d%d", &u, &v);
all.insert(u); //将节点加入集合
all.insert(v);
mp[u][v] = true; //存储无向边
mp[v][u] = true;
}
scanf("%d", &m);
while(m--){
init();
set<int>tall=all; //复制所有节点
scanf("%d", &k);
qur.resize(k);
for(int i = 0; i < k; i++){ //读入询问序列同时进行判断
scanf("%d", &qur[i]);
if(tall.find(qur[i])!=tall.end()) //删除询问序列中的点,剩余即为团外的点
tall.erase(tall.find(qur[i]));
}
for(int i = 0; i < k; i++) //判断是否为团——是否为完全图
for(int j = 0; j < i; j++)//对于询问序列的每个节点间判断是否相连,不相连则非团
if(mp[qur[i]][qur[j]]==false){flag=false;break;}//存在不相连的两节点,不是团
if(flag==false){printf("Not a Clique\n");continue;}
for(int it : tall){//对于团外的所有节点进行逐个判断
int i;
for(i = 0; i < k; i++) if(!mp[qur[i]][it]) break;
if(i >= k){printf("Not Maximal\n");flag=false;break;}//若存在一个点与团内所有点都相连,则团非最大团
}
if(flag)printf("Yes\n");
}
return 0;
}