PAT甲级1134Vertex Cover

题目链接

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

题目要求

  • vertex cover

    vertex cover指图中的每条边都和这组顶点中至少一个顶点相关,先给定一个图和几组顶点,请判断这几组顶点是否为vertex cover

  • 输入

    • N:顶点数量,不超过10000

    • M:边的数量,不超过10000

    • M条边:顶点通过[0,N-1]表示/索引

    • K:有几组顶点,不超过100

    • K组顶点

      一组顶点的第一个数字是顶点数量,剩下的是顶点索引

  • 输出

    • 是vertex则输出Yes,不是则输出No

题解一

思路

  • 定义Edge结构体,包括两个端点

  • 把M条边存入vector

  • 将顶点组存入set(vector也可以)

  • 遍历每条边判断其两个端点是否在set中

    只要有一条边的两个端点都不在set中,则不是vertex cover

代码

// Problem: PAT Advanced 1134
// URL: https://pintia.cn/problem-sets/994805342720868352/problems/994805346428633088
// Tags: Graph Hash Set

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

struct Edge{
    int v1, v2;
};

int main()
{
    int n, m, k;
    scanf("%d %d", &n, &m);
    
    vector<Edge> edges(m); // 存储边
    for (int i = 0; i < m; i++)
        scanf("%d %d", &edges[i].v1, &edges[i].v2);

    scanf("%d", &k);
    while (k--){
        set<int> vertices;
        int vertexNum, vertex;
        scanf("%d", &vertexNum);
        for (int i = 0; i < vertexNum; i++){ // 将一组顶点存入set
            scanf("%d", &vertex);
            vertices.insert(vertex);
        }

        bool isVertexCover = true;
        for (auto it = edges.begin(); it != edges.end(); it++){
            // 只要有一条边的两个端点都不在set中,则不是vertex cover
            if (vertices.find(it->v1) == vertices.end() && vertices.find(it->v2) == vertices.end()){
                isVertexCover = false;
                break;
            }
        }
        if (isVertexCover)
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}

题解二

比上一个方法快

思路

  • 给M条边编号为[0,M-1]
  • 读取每条边时,保存每个顶点与哪条边相关,将这个信息存入vector
  • 定义vector表示各条边是否被覆盖,遍历上一步得到的vector标记各条边是否被覆盖,最后遍历这一步定义的vector判断是否符合vertex cover的条件

注意点

  • 一个顶点可以和多条边相关

代码

// Problem: PAT Advanced 1134
// URL: https://pintia.cn/problem-sets/994805342720868352/problems/994805346428633088
// Tags: Graph Hash Set

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

int main()
{
    int n, m, k;
    scanf("%d %d", &n, &m);

    vector<int> cover[n]; // cover[2].push_back(3) 代表顶点2覆盖了边3
    int v1, v2;
    for (int i = 0; i < m; i++){
        scanf("%d %d", &v1, &v2);
        cover[v1].push_back(i);
        cover[v2].push_back(i);
    }

    scanf("%d", &k);
    while (k--){
        vector<bool> isCovered(m, false); // m条边是否被覆盖
        int vertexNum, vertex;
        scanf("%d", &vertexNum);
        for (int i = 0; i < vertexNum; i++){ // 遍历顶点,将其覆盖的边标记
            scanf("%d", &vertex);
            for (int j = 0; j < cover[vertex].size(); j++)
                isCovered[cover[vertex][j]] = true;
        }
        bool isVertexCover = true;
        for (int i = 0; i < m; i++){
            if (isCovered[i] == false){
                isVertexCover = false;
                break;       
            }
        }
        if (isVertexCover)
            printf("Yes\n");
        else
            printf("No\n");        
    }
    return 0;
}

参考链接

https://blog.csdn.net/liuchuo/article/details/78037329


作者:@臭咸鱼

转载请注明出处:https://www.cnblogs.com/chouxianyu/

欢迎讨论和交流!


posted @ 2020-09-01 22:21  臭咸鱼  阅读(174)  评论(0编辑  收藏  举报