给定一个无向图G,顶点编号为1到Nv,Ne条边,判断给出的一组顶点集合是否构成该图的一个极大彻底子图,若是是输出Yes,不然判断是不是一个彻底子图,若是是输出Not Maximal,不然输出Not a Clique。算法
首先得判断输入的集合是不是当前图G的一个彻底子图,这里采用isClique函数来实现,若是是就再判断是不是一个极大彻底子图,这里采用isMaximal来实现,最后就根据判断的结果进行相应的输出就好。函数
直接遍历输入集合的不一样顶点之间是否存在不邻接的点,若是是就返回false,不然返回true。spa
bool G[201][201];// 邻接矩阵,判断2点是否邻接 bool isClique(const vector<int> &a){ for(int i:a){ for(int j:a){ if(i!=j&&!G[i][j]){ // 存在不邻接的结点 return false; } } } return true; }
咱们使用exist标记全部输入的结点,而后遍历全部的顶点,只要没有出如今输入集合中而且与集合全部顶点都邻接,说明不是极大彻底子图,返回false,不然返回true。code
bool G[201][201];// 邻接矩阵,判断2点是否邻接 bool exist[201];// 标记每个在subset中的结点编号 bool isMaximal(const vector<int> &a,int N){ for(int i=1;i<=N;++i){ if(exist[i]) continue; bool isAllAdjcent = true; for(int j:a){ // 得判断i和全部的点是否邻接 if(!G[i][j]){ isAllAdjcent = false; break; } } if(isAllAdjcent){ // 能够扩展一个邻接点 return false; } } return true; }
#include<cstdio> #include<vector> #include<cstring> using namespace std; bool G[201][201];// 邻接矩阵,判断2点是否邻接 bool exist[201];// 标记每个在subset中的结点编号 bool isClique(const vector<int> &a){ for(int i:a){ for(int j:a){ if(i!=j&&!G[i][j]){ // 存在不邻接的结点 return false; } } } return true; } bool isMaximal(const vector<int> &a,int N){ for(int i=1;i<=N;++i){ if(exist[i]) continue; bool isAllAdjcent = true; for(int j:a){ // 得判断i和全部的点是否邻接 if(!G[i][j]){ isAllAdjcent = false; break; } } if(isAllAdjcent){ // 能够扩展一个邻接点 return false; } } return true; } int main(){ int Nv,Ne; scanf("%d %d",&Nv,&Ne); int a,b; for(int i=0;i<Ne;++i){ scanf("%d %d",&a,&b); G[a][b] = G[b][a] = true; } int M,N; scanf("%d",&M); for(int i=0;i<M;++i){ vector<int> subset; memset(exist,0,sizeof(exist)); scanf("%d",&N); for(int j=0;j<N;++j){ scanf("%d",&a); exist[a] = true; subset.push_back(a); } if(!isClique(subset)){ printf("Not a Clique\n"); }else if(!isMaximal(subset,Nv)) { printf("Not Maximal\n"); }else { printf("Yes\n"); } } return 0; }