个人练习-PAT甲级-1134 Vertex Cover

题目链接https://pintia.cn/problem-sets/994805342720868352/problems/994805346428633088

题目大意:给出一个图。如果一个点的集合能够包含所有的边,那么称其为一个vertex cover。集合内一个点包含以它为端点的所有边。给出K个query,每个query包含一个点的集合,判断其是否为vertex cover,是输出Yes,否则输出No

思路:开始想到的是图的节点与边的转换,DS课上好像学过。但想不起来【连接三条及以上的边的节点】如何转为边,于是想着先用暴力法做一遍吧。然后…竟然过了?我还以为至少要DFS什么的…

使用set来存包含了的边,这样不会重复。然后只需判断这个set的size是否达到M即可。

注意的点是无论如何,即使一个query中扫描到前几个点就足以覆盖整个图了,也要坚持把整个点集扫描完,不然之后的扫描就全乱了。

    for (int i = 0; i < K; i++) {
        bool flag = false;
        int Nv;
        set<int> have;
        scanf("%d", &Nv);
        for (int j = 0; j < Nv; j++) {
            int v;
            scanf("%d", &v);
            if (!flag) {
                for (int k = 0; k < edge[v].size(); k++) {
                    have.insert(edge[v][k]);
                    if (have.size() == M) {
                        flag = true;
                        break;
                    }
                }
            }
        }
        if (flag)
            printf("Yes\n");
        else
            printf("No\n");
    }

完整代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <algorithm>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>


using namespace std;


bool v2e[10001][10001];


int main() {
    int N, M, K;
    scanf("%d %d", &N, &M);
    vector<vector<int>> edge(N);
    for (int i = 0; i < M; i++) {
        int v1, v2;
        scanf("%d %d", &v1, &v2);
        edge[v1].push_back(i);
        edge[v2].push_back(i);
    }

    scanf("%d", &K);
    for (int i = 0; i < K; i++) {
        bool flag = false;
        int Nv;
        set<int> have;
        scanf("%d", &Nv);
        for (int j = 0; j < Nv; j++) {
            int v;
            scanf("%d", &v);
            if (!flag) {
                for (int k = 0; k < edge[v].size(); k++) {
                    have.insert(edge[v][k]);
                    if (have.size() == M) {
                        flag = true;
                        break;
                    }
                }
            }
        }
        if (flag)
            printf("Yes\n");
        else
            printf("No\n");
    }


    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值