PAT甲级 图 相关题_C++题解
图
PAT (Advanced Level) Practice 用到图的存储方式,但没有用到图的算法的题目
目录
- 1122 Hamiltonian Cycle (25)
- 1126 Eulerian Path (25)
- 1134 Vertex Cover (25)
- 1142 Maximal Clique (25)
- 1154 Vertex Coloring (25)
1122 Hamiltonian Cycle (25)
题目思路
- 用
n != queryV.size()
检查是否 query 覆盖了所有结点 - 用
kn != n + 1
检查 query 是否多走或少走 - 用
query[0] != query[kn-1]
检查是否成环 - 遍历 query 检查是否每一步都可到达
#include<iostream>
#include<unordered_set>
using namespace std;
bool G[201][201] = {false};
int main()
{
int n, m, u, v, k, kn;
scanf("%d%d", &n, &m);
for (int i = 0; i < m; i++){
scanf("%d%d", &u, &v);
G[u][v] = G[v][u] = true;
}
scanf("%d", &k);
for (int i = 0; i < k; i++){
scanf("%d", &kn);
int query[kn];
unordered_set<int> queryV;
for (int j = 0; j < kn; j++){
scanf("%d", &query[j]);
queryV.insert(query[j]);
}
bool isC = true;
for (int j = 0; j < kn - 1; j++)
if (!G[query[j]][query[j+1]]) isC = false;
if (!isC || kn != n + 1 || n != queryV.size() || query[0] != query[kn-1]) printf("NO\n");
else printf("YES\n");
}
return 0;
}
1126 Eulerian Path (25)
题目思路
- 用邻接表存储图,可以用每个结点对应邻接点的个数(
Adj[i].size()
)表示每个结点的度 - 题干给出根据度奇偶性和个数判断的先决条件是要是连通图
- 先用深搜判断连通,从任一结点开始,看可以遍历到多少结点
- 若遍历到的结点数与结点总数不同,则不是连通图,直接输出 Non-Eulerian
- 若相同则说明是连通图,再遍历邻接表输出结点度数并记录度数为奇数的结点个数
- 根据奇度数结点个数输出是否为 Eulerian
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
vector<int> Adj[501];
bool vis[501] = {false};
int connected = 0;
void DFS(int root){
connected++;
vis[root] = true;
for (int i = 0; i < Adj[root].size(); i++)
if (!vis[Adj[root][i]]) DFS(Adj[root][i]);
}
int main()
{
int n, m, u, v, oddnum = 0;
scanf("%d%d", &n, &m);
for (int i = 0; i < m; i++){
scanf("%d%d", &u, &v);
Adj[u].push_back(v);
Adj[v].push_back(u);
}
DFS(1);
for (int i = 1; i < n + 1; i++){
printf("%d%c", Adj[i].size(), i == n ? '\n' : ' ');
if (Adj[i].size() % 2) oddnum++;
}
if (connected != n) printf("Non-Eulerian\n");
else printf("%s\n", !oddnum ? "Eulerian" : oddnum == 2 ? "Semi-Eulerian" : "Non-Eulerian");
return 0;
}
简化前代码
- 用邻接矩阵存储图
- 单独开数组记录结点度数
- 用 BFS 判断是否连通
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
int G[501][501] = {0};
bool vis[501] = {false};
int main()
{
int n, m, u, v, connected = 0, oddnum = 0;
scanf("%d%d", &n, &m);
int degree[n+1] = {0};
for (int i = 0; i < m; i++){
scanf("%d%d", &u, &v);
degree[u]++;
degree[v]++;
G[u][v] = G[v][u] = 1;
}
queue<int> q;
q.push(n);
vis[n] = true;
while (!q.empty()){
int now = q.front();
q.pop();
connected++;
for (int i = 1; i < n + 1; i++){
if (!vis[i] && G[now][i]){
q.push(i);
vis[i] = true;
}
}
}
for (int i = 1; i < n + 1; i++){
printf("%d%c", degree[i], i == n ? '\n' : ' ');
if (degree[i] % 2) oddnum++;
}
if (connected != n) printf("Non-Eulerian\n");
else printf("%s\n", !oddnum ? "Eulerian" : oddnum == 2 ? "Semi-Eulerian" : "Non-Eulerian");
return 0;
}
1134 Vertex Cover (25)
题目思路
- 用
vector<pair<int,int>>
保存边的端点 - 对每个 query,新建一个 map 标记给出的 vertex
- 遍历所有边,检查是否有边两个端点均不在给出的 vertex 中
- 若有说明给出的 vertex 不能覆盖所有边,标记变量退出循环
- 按标记变量输出要求内容
#include<iostream>
#include<vector>
#include<unordered_map>
using namespace std;
int main()
{
int n, m, k, nv, v;
scanf("%d%d", &n, &m);
vector<pair<int,int>> edges(m);
for (int i = 0; i < m; i++) scanf("%d%d", &edges[i].first, &edges[i].second);
scanf("%d", &k);
for (int i = 0; i < k; i++){
scanf("%d", &nv);
unordered_map<int,bool> vertex;
bool iscover = true;
for (int j = 0; j < nv; j++){
scanf("%d", &v);
vertex[v] = true;
}
for (int j = 0; j < m; j++){
if (!vertex[edges[j].first] && !vertex[edges[j].second]){
iscover = false;
break;
}
}
printf("%s\n", iscover ? "Yes" : "No");
}
return 0;
}
1142 Maximal Clique (25)
题目思路
- 输入无向边,用邻接矩阵将两个方向的边均存储起来
- 每输入一个待检查的序列,就将标记变量
isclique
&isMax
均设为true
,新建保存序列的数组和保存序列结点的集合 - 输入待查序列同时将结点压入集合
- 首先用二重循环检查序列是否两两相邻,若不是,说明现有序列非 clique,设置标记输出内容并跳出循环
- 若通过上个检查,已知是 clique,要检查是否是最大的,也就是是否有其他结点与序列中每个点都相邻
- 用一个变量按顺序遍历结点标号,取出不在序列中的结点,与序列结点两两配对检查是否相邻
- 若有一对不相邻就从序列结点中 break 取下一个结点
- 若能一直检查到序列结尾,发现此结点与序列每个结点均相邻,说明现有序列非 max clique,设置标记输出内容跳出循环
- 最后检查变量按要求输出内容
#include<iostream>
#include<set>
using namespace std;
bool G[201][201] = {false};
int main()
{
int nv, ne, u, v, m, K;
scanf("%d%d", &nv, &ne);
for (int i = 0; i < ne; i++){
scanf("%d%d", &u, &v);
G[u][v] = G[v][u] = true;
}
scanf("%d", &m);
for (int i = 0; i < m; i++){
bool isclique = true, isMax = true;
scanf("%d", &K);
int clique[K];
set<int> cliqueV;
for (int j = 0; j < K; j++){
scanf("%d", &clique[j]);
cliqueV.insert(clique[j]);
}
for (int j = 0; j < K - 1; j++){
for (int k = j + 1; k < K; k++){
if (!G[clique[j]][clique[k]]){
isclique = false;
printf("Not a Clique\n");
break;
}
}
if (!isclique) break;
}
if (isclique){
for (int j = 1; j <= nv; j++){
if (cliqueV.find(j) == cliqueV.end()){
for (int k = 0; k < K; k++){
if (!G[clique[k]][j]) break;
if (k == K - 1) isMax = false;
}
}
if (!isMax){
printf("Not Maximal\n");
break;
}
}
if (isMax) printf("Yes\n");
}
}
return 0;
}
1154 Vertex Coloring (25)
题目思路
- 用
vector<pair<int,int>>
保存所有边 - 将所有点的颜色存起来,同时放入set统计颜色个数
- 枚举所有边,检查是否每条边的两点个颜色是否相同
- 若有相同的边,设置标记
- 根据标记 输出颜色个数 或 输出No
#include<iostream>
#include<vector>
#include<set>
using namespace std;
int main()
{
int n, m, k, u, v;
scanf("%d%d", &n, &m);
vector<pair<int,int>> edges(m);
for (int i = 0; i < m; i++)
scanf("%d%d", &edges[i].first, &edges[i].second);
scanf("%d", &k);
for (int i = 0; i < k; i++){
vector<int> colors(n);
set<int> coloring;
bool isokay = true;
for (int j = 0; j < n; j++){
scanf("%d", &colors[j]);
coloring.insert(colors[j]);
}
for (int j = 0; j < m; j++)
if (colors[edges[j].first] == colors[edges[j].second])
isokay = false;
if (!isokay) printf("No\n");
else printf("%d-coloring\n", coloring.size());
}
return 0;
}
PAT甲级 图 相关题_C++题解的更多相关文章
- PAT甲级 Dijkstra 相关题_C++题解
Dijkstra PAT (Advanced Level) Practice Dijkstra 相关题 目录 <算法笔记>重点摘要 1003 Emergency (25) <算法笔记 ...
- PAT甲级 二叉树 相关题_C++题解
二叉树 PAT (Advanced Level) Practice 二叉树 相关题 目录 <算法笔记> 重点摘要 1020 Tree Traversals (25) 1086 Tree T ...
- PAT甲级 二叉查找树 相关题_C++题解
二叉查找树 PAT (Advanced Level) Practice 二叉查找树 相关题 目录 <算法笔记> 重点摘要 1099 Build A Binary Search Tree ( ...
- PAT甲级 树 相关题_C++题解
树 目录 <算法笔记>重点摘要 1004 Counting Leaves (30) 1053 Path of Equal Weight (30) 1079 Total Sales of S ...
- PAT甲级 堆 相关题_C++题解
堆 目录 <算法笔记>重点摘要 1147 Heaps (30) 1155 Heap Paths (30) <算法笔记> 9.7 堆 重点摘要 1. 定义 堆是完全二叉树,树中每 ...
- PAT甲级 散列题_C++题解
散列 PAT (Advanced Level) Practice 散列题 目录 <算法笔记> 重点摘要 1002 A+B for Polynomials (25) 1009 Product ...
- PAT甲级 字符串处理题_C++题解
字符串处理题 目录 <算法笔记> 重点摘要 1001 A+B Format (20) 1005 Spell It Right (20) 1108 Finding Average (20) ...
- PAT甲级 图的遍历 相关题_C++题解
图的遍历 PAT (Advanced Level) Practice 图的遍历 相关题 目录 <算法笔记>重点摘要 1021 Deepest Root (25) 1076 Forwards ...
- PAT甲级 并查集 相关题_C++题解
并查集 PAT (Advanced Level) Practice 并查集 相关题 <算法笔记> 重点摘要 1034 Head of a Gang (30) 1107 Social Clu ...
随机推荐
- Ubuntu16.04 apache2+php7.0+mysql5.7环境搭建
今天配置一下web环境,很常见的apache+php+mysql的网站环境: 步骤一:安装apache sudo apt install apache2 步骤二:安装php7 1.安装PHP7和响应的 ...
- 走进JavaWeb技术世界7:Tomcat中的设计模式
. 门面设计模式 门面设计模式在 Tomcat 中有多处使用,在 Request 和 Response 对象封装中.Standard Wrapper 到 ServletConfig 封装中.Appli ...
- 使用python3安装frida-tools出错
执行安装命令 pip3.6 install frida-tools 得到错误信息 error: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] c ...
- django + vue3 解决跨越问题
django跨域 解决: https://yq.aliyun.com/articles/517215 vue3 跨越(此处没必要,django处理即可): https://blog.csdn.net/ ...
- What is the difference between XSS and CSRF from their execution perspective?
What is the difference between XSS and CSRF from their execution perspective? https://www.quora.com/ ...
- python pip 安装插件权限问题及 指定pip国内镜像源
- python 简化数据结构的初始化二 支持关键字参数
1.例子 学自cookbook3
- redis修改持久化路径、日志路径、清缓存
redis修改持久化路径和日志路径 vim redis.conf logfile /data/redis_cache/logs/redis.log #日志路径 dir /data/redis_cach ...
- linux性能监控 -CPU、Memory、IO、Network等指标的讲解
[操作系统-linux]linux性能监控 -CPU.Memory.IO.Network等指标的讲解(转) 一.CPU 1.良好状态指标 CPU利用率:User Time <= 70%,Syst ...
- NPM 私服
下载https://nodejs.org/en/download/ linux binaries x64版本xz -d ....xztar -xvf ....tar导入path修改~/.bashrc加 ...