题目链接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;
}