题目链接
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
");
else
printf("No
");
}
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
");
else
printf("No
");
}
return 0;
}
参考链接
https://blog.csdn.net/liuchuo/article/details/78037329
作者:@臭咸鱼
转载请注明出处:https://www.cnblogs.com/chouxianyu/
欢迎讨论和交流!