PAT-A1142 Maximal Clique 题目内容及题解

该博客介绍了如何判断一个给定的顶点子集是否能构成图的最大团。首先,博客提供了输入输出规格,然后详细解释了最大团的概念。接着,博主分享了解题思路,包括使用邻接矩阵和邻接表存储图信息,并对每个查询进行验证。博主给出了代码实现,并展示了样例输入和输出,最后验证解法的正确性。
摘要由CSDN通过智能技术生成

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. 建立vis数组,并归零;
  5. 对序列中每个顶点查看其邻接表,并将邻接表中元素加一;
  6. 将vis数组中在查询序列中的位置归零;
  7. 遍历vis数组,如果找到记录为查询序列元素数的记录,则说明存在其他相邻顶点,输出非最大团,并开始下一次验证;
  8. 验证成功输出是,并返回开始下一次验证;
  9. 验证所有序列结束后返回零值。

代码

#include<cstdio>
#include<vector>
using namespace std;
#define maxn 210

int E[maxn][maxn];
vector<int> Adj[maxn];
vector<int> vis;
int Nv,Ne,M;

void Init(){
    int a,b;
    scanf("%d%d",&Nv,&Ne);
    while(Ne--){
        scanf("%d%d",&a,&b);
        E[a][b]=1;
        E[b][a]=1;
        Adj[a].push_back(b);
        Adj[b].push_back(a);
    }
    scanf("%d",&M);
}

void Check(){
    int i,j,K,a,b;
    vector<int> seq;
    scanf("%d",&K);
    for(i=0;i<K;i++){
        scanf("%d",&a);
        seq.push_back(a);
    }
    for(i=0;i<K;i++){
        a=seq[i];
        for(j=i+1;j<K;j++){
            b=seq[j];
            if(E[a][b]==0){
                printf("Not a Clique\n");
                return;
            }
        }
    }
    vis.clear();
    vis.resize(Nv+1);
    for(i=0;i<seq.size();i++){
        a=seq[i];
        for(j=0;j<Adj[a].size();j++){
            vis[Adj[a][j]]++;
        }
    }
    for(i=0;i<seq.size();i++){
        vis[seq[i]]=0;
    }
    for(i=0;i<=Nv;i++){
        if(vis[i]==K){
            printf("Not Maximal\n");
            return;
        }
    }
    printf("Yes\n");
}

int main(){
    Init();
    while(M--){
        Check();
    }
    return 0;
}

运行结果

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值