目的:判断顶点子集是否可以形成一个最大的clique
输入:
Nv <=200 顶点数目
Ne 无向边的数目
然后Ne条边,每条边有两个顶点。
顶点从1——Nv编号
M<=100 查询数目
查询格式:
k<=Nv k个不同顶点的序列
输出:
Yes 如果顶点的子集合可以形成一个最大的clique
Not Maximal 如果是一个clique,但不是最大的
Not a Clique 如果不是clique。
算法:
判断是不是Clique。
二重循环判断是不是每条边都存在。
再判断是不是最大的。
往里面加点,看可不可以,可以就不是最大的。
只有两百个顶点,那么就可以用邻接矩阵。
然后用一个vector存每个查询的序列,一个vector存哪些顶点在,免得添加顶
点的时候加重了。
#include<stdio.h>
#include<vector>
using namespace std;
const int maxn = 210;
int Nv,Ne;
int m,k;
bool g[maxn][maxn] = {false};
vector<int> query;
bool isclique()
{
for(int i=0;i<k-1;i++)
{
int u = query[i];
for(int j=i+1;j<k;j++)
{
int v = query[j];
if(g[u][v]==false)
{
return false;
}
}
}
return true;
}
int main()
{
scanf("%d%d",&Nv,&Ne);
for(int i=0;i<Ne;i++)
{
int u = 0,v = 0;
scanf("%d%d",&u,&v);
g[u][v] = true;
g[v][u] = true;
}
scanf("%d",&m);
for(int i=0;i<m;i++)
{
scanf("%d",&k);
query.clear();
vector<int> a(maxn,0);
for(int j=0;j<k;j++)
{
int x;
scanf("%d",&x);
query.push_back(x);
a[x] = 1;
}
if(isclique()==false)
{
printf("Not a Clique\n");
}else{
int tag = 0;
for(int j=1;j<=Nv;j++)
{
int u = j;
if(a[j]==0)
{
int flag = 0;
for(int l=0;l<k;l++)
{
int v = query[l];
if(g[u][v]==false)
{
flag = 1;
break;
}
}
if(flag==0)
{
tag = 1;
break;
}
}
}
if(tag==1)
{
printf("Not Maximal\n");
}else
{
printf("Yes\n");
}
}
}
return 0;
}
反思:是内容还是下标,容易弄混,要清晰一点。ijk这些,不要重名了,这是容易出错的地方。