1. 程式人生 > 實用技巧 >PAT甲級1142Maximal Clique

PAT甲級1142Maximal Clique

題目連結

https://pintia.cn/problem-sets/994805342720868352/problems/994805343979159552

題解

題目要求

  • 團:某無向圖的一個頂點子集,其中任意兩個不同的頂點相鄰,則這個頂點子集是這個圖的一個團。
  • 極大團:如果一個團在加入任何一個頂點後都不再是一個團,則這個團是一個極大團。

現在給你一個圖,請你判斷一些點集是否是團或極大團。

  • 輸入

    • Nv:正整數,不超過200,圖中頂點的數量
    • Ne:正整數,圖中邊的數量
    • Ne條邊:頂點索引為[1,Nv]
    • M:正整數,不超過100,需要判斷的頂點子集的個數
    • M個頂點子集:第一個數字k是頂點個數(不超過Nv),剩下的數字是頂點索引
  • 輸出

    對於每個頂點子集,請判斷它是最大團還是最大團以外的團或者不是團

思路

  1. 使用鄰接矩陣儲存邊,用二維陣列表示

  2. 使用vector儲存頂點子集,並使用set儲存頂點子集以外的頂點

  3. 根據定義判斷頂點子集中的頂點是否兩兩相鄰,如果是則為團,不是則不是團

  4. 如果是團,根據最大團的定義,遍歷頂點子集以外的頂點,判斷是否可以再新增一個頂點且該頂點與頂點子集中每個頂點都相鄰

    如果可以則說明不是極大團,不可以則不是極大團

程式碼

// Problem: PAT Advanced 1142
// URL: https://pintia.cn/problem-sets/994805342720868352/problems/994805343979159552
// Tags: Graph Clique Maximal Clique

#include <iostream>
#include <vector>
#include <set>
using namespace std;

bool edge[201][201];

int main()
{
    int ne, nv, m;
    scanf("%d %d", &nv, &ne);

    int v1, v2;
    for (int i = 0; i < ne; i++){ // 記錄邊
        scanf("%d %d", &v1, &v2);
        edge[v1][v2] = edge[v2][v1] = true;
    }

    scanf("%d", &m);
    while (m--){ // 判斷m個頂點子集
        set<int> leftV; // 該頂點子集以外的結點
        for (int i = 1; i <= nv; i++){
            leftV.insert(i);
        }
        int k;
        scanf("%d", &k);
        vector<int> v(k);
        for (int i = 0; i < k; i++){ // 記錄頂點子集
            scanf("%d", &v[i]);
            leftV.erase(v[i]);
        }

        bool isClique = true; // 先判斷是否是團
        for (int i = 0; i < k - 1; i++){
            for (int j = i + 1; j < k; j++){
                if (edge[v[i]][v[j]] == false){
                    isClique = false;
                    break;
                }
            }
            if (isClique == false)
                break;
        }

        if (isClique == false){
            printf("Not a Clique\n");
            continue;
        }

        bool isMaximalClique = true; // 如果是團,再判斷是不是極大團(按照定義判斷)
        for (auto it = leftV.begin(); it != leftV.end(); it++){
            int cnt = 0;
            for (int i = 0; i < k; i++){
                if (edge[*it][v[i]] == true)
                    cnt++;
            }
            if (cnt == k){
                isMaximalClique = false;
                break;
            }
        }

        if (isMaximalClique) printf("Yes\n");
        else printf("Not Maximal\n");
    }
    return 0;
}

作者:@臭鹹魚

轉載請註明出處:https://www.cnblogs.com/chouxianyu/

歡迎討論和交流!