【PAT甲级】1142 Maximal Clique

✍个人博客:https://blog.csdn.net/Newin2020?spm=1011.2415.3001.5343
📚专栏地址:PAT题解集合
📝原题地址:题目详情 - 1142 Maximal Clique (pintia.cn)
🔑中文翻译:最大团
📣专栏定位:为想考甲级PAT的小伙伴整理常考算法题解,祝大家都能取得满分!
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪

1142 Maximal Clique

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] 就是该图的最大团,而 5 不在其中是因为 532 没有边。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XF92mo07-1666694033727)(PAT 甲级辅导.assets/18.png)]

思路
  1. 这题用邻接矩阵来存储每一条边。
  2. 每次询问时用数组 vers 去存储每个点值,并用 cnt 记录点数。然后先判判断该子集是否是团,如果是团再进一步判断是否为最大团。
    1. 判断是否是团,只需判断子集中每个点之间是否都存在边。
    2. 判断是否为最大团,需要先用一个数组 st 来标记子集中有哪些点,然后再遍历不是子集中的点,再去判断这些点是否和子集中的每个点都存在一条边,只要能找到一个这种点,就说明不是最大团。
  3. 根据判断结果,输出对应语句。
代码
#include<bits/stdc++.h>
using namespace std;

const int N = 210;
int g[N][N];
int vers[N];
bool st[N];
int n, m;

//判断是不是团
bool check_clique(int cnt)
{
    //判断每个点之间是否都存在边
    for (int i = 0; i < cnt; i++)
        for (int j = 0; j < i; j++)
            if (!g[vers[i]][vers[j]])
                return false;
    return true;
}

//判断是不是最大团
bool check_maximum(int cnt)
{
    memset(st, 0, sizeof st); //初始化
    //先将子集中的点进行标记
    for (int i = 0; i < cnt; i++)  st[vers[i]] = true;

    //然后遍历不在子集中的点
    for (int i = 1; i <= n; i++)
        if (!st[i])
        {
            //判断该点是否与子集中的所有点都有边
            bool success = true;
            for (int j = 0; j < cnt; j++)
                if (!g[i][vers[j]])
                {
                    //只要子集中有一个点与其没边,该点就不属于该团
                    success = false;
                    break;
                }

            //根据遍历结果判断是否为最大团
            if (success) return false;
        }

    return true;
}

int main()
{
    cin >> n >> m;

    //记录每条边
    for (int i = 0; i < m; i++)
    {
        int a, b;
        cin >> a >> b;
        g[a][b] = g[b][a] = true;
    }

    //开始查询
    int k;
    cin >> k;
    while (k--)
    {
        int cnt;
        cin >> cnt;
        for (int i = 0; i < cnt; i++)    cin >> vers[i];   //输入子集

        //判断是不是团
        if (check_clique(cnt))
        {
            //判断是不是最大团
            if (check_maximum(cnt))  puts("Yes");
            else    puts("Not Maximal");
        }
        else    puts("Not a Clique");
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值