pat甲级 顶点覆盖 题型:图论

71 阅读2分钟

中文题目:1627. 顶点覆盖 - AcWing题库

英文题目:1134 Vertex Cover - PAT (Advanced Level) Practice (pintia.cn)

题意解析

首先给n个点m条边,我们去建图,然后再给我们K个顶点,让我们判断这k个顶点是否落在图中的每一条边的顶点上。(一条边至少落一个顶点),如果满足输出“yes”,否则输出“No”。

样例模拟

这是根据样例画的9个节点10条边:image.png

这是第一个询问,0 3 8 4:

image.png

我们发现1~2这条边和1~9这条边没有1个顶点在给定的图中,输出“NO”:

image.png

第二个询问,6,1,7,5,4,9:

image.png 我们发现每条边都至少有一个顶点位于图中,输出“yes”。

第三个询问,1,8,4:

image.png 我们发现每条边都至少有一个顶点位于图中,输出“yes”。

第四个询问,2,8:

image.png

我们发现 1~0,1~9,1~4,4~5 这几条边没有1个顶点在图中,输出“NO”:

image.png

第五个询问,9 8 7 6 5 4 2

image.png

我们发现1~0这条边没有1个顶点在图中,输出"NO":

image.png

code

每次询问使用bool st[N]保存访问到的点

遍历所有边,一个边至少有1个点被访问,否则输出No

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

//复杂度
//最多10000条边,100次询问,每次询问访问的点不超过10000,最多1e6

//思路:
//1. 将组合每一条边的两个点保存到集合中
int n,m;
vector<pair<int,int>> arr;
//2. 每次询问使用bool st[N]保存访问到的点
const int N = 10010;
bool st[N];
//3. 遍历所有边,一个边至少有1个点被访问,否则输出No

int main(){
    cin >> n >> m;
    while(m--){
        int a,b; //组成边的a和b两点
        cin >> a >> b;
        arr.push_back({a,b});
    }

    int q; //query
    cin >> q;
    while(q--){
        memset(st,false,sizeof st);
        int k; //每次询问,访问的总点数
        cin >> k;

        while(k--){
            int a; //访问的点
            cin >> a;

            st[a] = true;
        }

        int i = 0;
        for(; i < arr.size(); i++){
            if(!st[arr[i].first] && !st[arr[i].second]) break;
        }

        if(i == arr.size()) puts("Yes");  //如果能走到末尾,说明每个点都被遍历到了
        else puts("No");
    }

    return 0;
}