5.图论.题目2

news2024/9/20 0:29:31

5.图论.题目2

  • 题目
    • 8.字符串接龙
    • 9.有向图的完全可达性
    • 10.岛屿的周长
    • 11.寻找存在的路径
    • 12.冗余连接1
    • 13.冗余连接2
    • 14.寻宝

题目

8.字符串接龙

题目链接
在这里插入图片描述
本题的直观思路如下图所示;但该题有两个问题:1.图中的线是如何连接起来的 2.如何确定起点到终点的最短路径。题中没给出节点之间的连线,条件是字符智能差一个。这里无向图求最短路,广搜最为合适,广搜只要搜到了终点,那么一定是最短的路径。因为广搜就是以起点中心向四周扩散的搜索。另外得注意

  • 本题是无向图,需要用标记位,标记节点是否遍历过,否则就会死循环
  • 使用set检查字符串是否出现过会更快
    在这里插入图片描述
#include <iostream>
#include "vector"
#include "queue"
#include "unordered_map"
#include "unordered_set"

using namespace std;


int main(){
    string beginstr, endstr, strlist;
    int n;
    cin >>n;
    unordered_set<string> set; // store all the strings
    cin>> beginstr>> endstr;
    for(int i=0; i<n; i++) {
        cin >> strlist;
        set.insert(strlist);
    }
    queue<string> q;
    q.push(beginstr);

    unordered_map<string, int> visited;
    visited[beginstr] = 1;
    while(!q.empty()) {
        string curstr = q.front();
        q.pop();
        int path = visited[curstr];
        for(int i=0; i<curstr.size(); i++){
            string newstr = curstr;
            for(int j=0; j<26; j++){
                newstr[i] = 'a'+j;
                if(newstr == endstr){
                    cout<< path+1<< endl;
                    return 0;
                }
                if(set.find(newstr)!=set.end() && visited.find(newstr)==visited.end()){
                    q.push(newstr);
                    visited[newstr] = path+1;
                }
            }
        }
    }
    cout<< 0<< endl;
    return 0;
}

9.有向图的完全可达性

题目链接
在这里插入图片描述
题目要求判断节点的完全可达性;有向图搜索全路径的问题。 只能用深搜(DFS)或者广搜(BFS)来搜。
1.确认递归函数,参数:需要传入地图,需要知道key(知道下一步的节点)。同时需要一个数组,记录已经遍历的节点,这样才能判断有无将所有的节点已经遍历。
2.终止条件:因为在深度搜索时,没进入下一层搜索,是根据当前节点所对的邻接表key-list中的指向的节点,因此这是有限的遍历,当把邻接表所有的边遍历完,即可退出。

#include <iostream>
#include "vector"
#include "list"

using namespace std;

void dfs(const vector<list<int>>& graph, int key, vector<bool>& visited){
    list<int> adjs = graph[key];
    for(int adj: adjs){
        if(!visited[adj]){
            visited[adj] = true;
            dfs(graph, adj, visited);
        }
    }
}


int main(){
    int n,m,s,t;
    cin>> n>> m;
    vector<list<int>> graph(n+1);
    while(m--){
        cin >>s >>t;
        graph[s].push_back(t);
    }
    vector<bool> visited(n+1,false);
    visited[1] = true;
    dfs(graph, 1, visited);
    for(int i=1; i<=n; i++){
        if(!visited[i]){
            cout<< -1<< endl;
            return 0;
        }
    }
    cout<< 1<< endl;
    return 0;
}

10.岛屿的周长

题目链接
在这里插入图片描述
求中间岛屿的周长,如果是使用dfs,bfs搜索算法的话,就是当发现并遍历岛屿时,每遍历一个节点,就计算其四周临近海水的边数,统计总数即可。
但其实本题是可以不适用dfs,bfs搜索算法,直接执行全图的遍历,当遍历到陆地时,检查其四周节点的情况,当四周是海水,或者超出图范围时,可认为是其边界。

#include <iostream>
#include "vector"

using namespace std;


int main(){
    int n,m,s,t;
    cin>> n>> m;
    vector<vector<int>> graph(n, vector<int>(m, 0));
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            cin>> graph[i][j];
        }
    }
    int dir[4][2] = {0, 1, 1, 0,-1,0,0,-1};
    int res = 0;
    for(int i=0;i<n;i++) {
        for (int j = 0; j < m; j++) {
            if (graph[i][j] == 1) {
                for (auto &d: dir) {
                    int x = i + d[0];
                    int y = j + d[1];
                    if(x<0 || x>=n || y<0 || y>=m || graph[x][y]==0) res++;
                }
            }
        }
    }
    cout<<res<<endl;
    return 0;
}

11.寻找存在的路径

题目链接
在这里插入图片描述
这题是并查集的基础题目,并查集解决的集合问题:1)判断两个节点在不在一个集合 2)将来两个节点添加到一个集合中

#include <iostream>
#include "vector"

using namespace std;

int n; // number of nodes
vector<int> father(n+1, 0);

// Union-Find Set's initialize Fucntion
void init(){
    for(int i=0;i<=n;i++){
        father[i] = i;
    }
}

// Union-Find Set's Find Function
int find(int u){
    return u == father[u]? u : father[u] = find(father[u]); // path compression 路径压缩
}

// Union-Find Set's Union Function
void join(int u, int v){
    u = find(u);
    v = find(v);
    if(u!= v) {
        father[v] = u;
    }
}

// Union-Finds Set's isSame Function
bool isSame(int u, int v){
    u = find(u);
    v = find(v);
    return u == v;
}

int main(){
    int m, s, t, source , destination;
    cin>> n>> m;
    init();
    while(m--){
        cin>> s>> t;
        join(s, t);
    }
    cin>> source>> destination;
    if(isSame(source, destination)) cout<< 1<< endl;
    else cout<< 0<< endl;
    return 0;
}

12.冗余连接1

题目链接
在这里插入图片描述
题目说是无向图,返回一条可以删去的边,使得结果图是一个有着N个节点的树(即:只有一个根节点)。如果有多个答案,则返回二维数组中最后出现的边。因此我们可以从前向后遍历边,边的两个节点如果不是在通过一个集合,就加入同一个集合(即,同一个根节点);如果两个节点已经在同一个集合,不添加改变,避免成环(无法成为树)。

#include <iostream>
#include "vector"

using namespace std;

int n; // number of nodes
vector<int> father(n+1, 0);

void init(){
    for(int i=0;i<=n;i++){
        father[i] = i;
    }
}

// Union-Find Set's Find Function
int find(int u){
    return u == father[u]? u : father[u] = find(father[u]); // path compression
}

// Union-Find Set's Union Function
void join(int u, int v){
    u = find(u);
    v = find(v);
    if(u!= v) {
        father[v] = u;
    }
}

// Union-Finds Set's isSame Function
bool isSame(int u, int v){
    u = find(u);
    v = find(v);
    return u == v;
}

int main(){
    int s,t;
    cin>> n;
    init();
    for(int i=0;i<n;i++){
        cin>> s>> t;
        if(isSame(s, t)){
            cout<< s<< " "<< t<< endl;
            return 0;
        }
        else{
            join(s, t);
        }
    }
    return 0;
}

13.冗余连接2

题目链接
本题的本质是 :有一个有向图,是由一颗有向树 + 一条有向边组成的 (所以此时这个图就不能称之为有向树),现在让我们找到那条边 把这条边删了,让这个图恢复为有向树,而且考虑若有多条边可以删除,请输出标准输入中最后出现的一条边。

有向树的特征是,节点的父子点是唯一的,即节点的入度是1;而且不能成环,必有一个节点的父子点是其自己,分为可以分为以下三种情况:
1.情况一:如果我们找到入度为2的点,那么删一条指向该节点的边就行了
在这里插入图片描述
2.情况二:节点3 的入度为 2,但在删除边的时候,只能删 这条边(节点1 -> 节点3),如果删这条边(节点4 -> 节点3),那么删后本图也不是有向树了(因为找不到根节点)
在这里插入图片描述
3.情况三:没有入度为2的点,说明 图中有环了,删除构成环的边(最后形成的)就可以了
在这里插入图片描述
给出代码

#include <iostream>
#include "vector"

using namespace std;

int n; // number of nodes
vector<int> father;

void init(){
    for(int i=0;i<=n;i++){
        father[i] = i;
    }
}

// Union-Find Set's Find Function
int find(int u){
    return u == father[u]? u : father[u] = find(father[u]); // path compression
}

// Union-Find Set's Union Function


void join(int u, int v){
    u = find(u);
    v = find(v);
    if(u!= v) {
        father[v] = u;
    }
}

// Union-Finds Set's isSame Function
bool isSame(int u, int v){
    u = find(u);
    v = find(v);
    return u == v;
}

bool isTreeaftermove(const vector<vector<int>>& edges, int delete_index){
    init();
    for(int i=0;i<n;i++){
        if(i==delete_index) continue;
        if(isSame(edges[i][0], edges[i][1])) return false; // 出现环
        join(edges[i][0], edges[i][1]);
    }
    return true; // 无环
}

void moveEdge(const vector<vector<int>>& edges){
    init();
    for(int i=0;i<n;i++){
        if(isSame(edges[i][0], edges[i][1])){
            cout<< edges[i][0]<< " " << edges[i][1]<< endl;
            return;
        }
        else{
            join(edges[i][0], edges[i][1]);
        }
    }
    return;
}

int main(){
    int s,t;
    cin>> n;
    father.resize(n+1,0);
    vector<vector<int>> edges(n, vector<int>(2,0)); // 存储边
    vector<int> indegree(n+1, 0); // 记录t节点的入度
    for(int i=0;i<n;i++){
        cin>> s>> t;
        edges[i][0] = s;
        edges[i][1] = t;
        indegree[t]++;
    }

    vector<int> vec; // 记录edges中使得出现入度位2节点出现的边的下标
    for(int i=n-1;i>=0;i--){
        if(indegree[edges[i][1]]==2) vec.push_back(i);
    }


    if(!vec.empty()){
        // 处理入度为2的边的节点 vec中有且只有2个元素
        if(isTreeaftermove(edges, vec[0])){
            cout<< edges[vec[0]][0]<< " " << edges[vec[0]][1]<< endl;
        }
        else {
            cout << edges[vec[1]][0] << " " << edges[vec[1]][1] << endl;
        }
        return 0;
    }
    else{
        // 处理自成环的节点
        moveEdge(edges);
        return 1;
    }
}

14.寻宝

题目链接
在这里插入图片描述
本题是最小生成树的模板题,最小生成树 可以使用 prim算法 也可以使用 kruskal算法计算出来。

最小生成树是所有节点的最小连通子图, 即:以最小的成本(边的权值)将图中所有节点链接到一起。图中有n个节点,那么一定可以用 n - 1 条边将所有节点连接到一起。那么如何选择 这 n-1 条边 就是 最小生成树算法的任务所在。
在这里插入图片描述
prim算法核心就是三步,我称为prim三部曲,大家一定要熟悉这三步:

  • 第一步,选距离生成树最近节点
  • 第二步,最近节点加入生成树
  • 第三步,更新非生成树节点到生成树的距离(即更新minDist数组)
    prim算法代码:
#include <iostream>
#include "vector"
#include "climits"

using namespace std;

int main(){
    int v, e; // 节点数,边数
    int x, y, k;
    cin>> v>> e;
    vector<vector<int>> graph(v+1, vector<int>(v+1, INT_MAX));
    for(int i=0; i<e; i++){
        cin>> x>> y>> k;
        graph[x][y] = k;
        graph[y][x] = k;
    }
    vector<int> minDist(v+1, INT_MAX);
    vector<bool> visited(v+1, false);
    vector<int> parent(v+1, -1);  // 用于记录每个节点i能被到达的父节点

    for(int i=1; i<=v; i++){
        // 从i=1出发,默认根节点是1
        int cur = -1;
        int minVal = INT_MAX;
        // 选择距离源点最近的节点作检查
        for(int j=1; j<=v; j++){
            if(!visited[j] && minDist[j] < minVal){
                minVal = minDist[j];
                cur = j;
            }
        }
        // 更新minDist
        visited[cur] = true;
        for(int j=1; j<=v; j++){
            if(!visited[j] && graph[cur][j] < minDist[j]){
                minDist[j] = graph[cur][j];
                parent[j] = cur; // 记录边
            }
        }
    }
    int res = 0;
    for(int i=2; i<=v; i++){
        res += minDist[i];
    }
    cout<< res<< endl;
    return 0;
}

prim 算法是维护节点的集合,而 Kruskal 是维护边的集合。kruscal的思路:

  • 边的权值排序,因为要优先选最小的边加入到生成树里
  • 遍历排序后的边:1)如果边首尾的两个节点在同一个集合,说明如果连上这条边图中会出现环 2)如果边首尾的两个节点不在同一个集合,加入到最小生成树,并把两个节点加入同一个集合
    kruskal算法实现
在这里插入代码片

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2095079.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《JavaEE进阶》----4.<SpringMVC①简介、基本操作(各种postman请求)>

本篇博客讲解 MVC思想、及Spring MVC&#xff08;是对MVC思想的一种实现&#xff09;。 Spring MVC的基本操作、学习了六个注解 RestController注解 RequestMappering注解 RequestParam注解 RequestBody注解 PathVariable注解 RequestPart注解 MVC View(视图) 指在应⽤程序中…

数据同步的艺术:探索PostgreSQL和Redis的一致性策略

作者&#xff1a;后端小肥肠 &#x1f347; 我写过的文章中的相关代码放到了gitee&#xff0c;地址&#xff1a;xfc-fdw-cloud: 公共解决方案 &#x1f34a; 有疑问可私信或评论区联系我。 &#x1f951; 创作不易未经允许严禁转载。 1. 前言 在当今高度数字化的世界中,应用程…

ACL学习笔记

1.ACL快速配置 需求&#xff1a;拒绝PC 1访问PC 3 &#xff08;1&#xff09;配置PC PC 1: PC 2: PC 3: &#xff08;2&#xff09;配置R1的接口IP信息 sys sysname R1 undo info-center enable interface GigabitEthernet0/0/0 ip address 192.168.1.1 255.255.255.0 qui…

超声波智能水表多少钱一个?

超声波智能水表的价格因品牌、功能、规格等因素而异&#xff0c;就拿深圳合众致达科技有限公司智能水电表厂家的超声波智能水表DN15口径产品举例&#xff0c;价格为399元起。具体价格需根据实际需求来确定。 一、影响价格的主要因素 -技术含量&#xff1a;具备远程数据传输、…

DSOJ-id12

1.保留几位小数 #include <iostream>#include <iomanip> //必须包含这个头文件using namespace std;void main( ){ double a 3.141596;cout<<fixed<<setprecision(3)<<a<<endl; //输出小数点后3位 2. 使用了未初始化的局部变量 Point* …

如何使用小乌龟清除认证缓存、还原版本、定位及常用开发工具集成

&#x1f600;前言 本篇博文是关于如何使用小乌龟清除认证缓存、还原版本、定位及常用开发工具集成&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大…

openGuass之CTE Reuse

一. 前言 ​ CTE 是指with的公共表达式&#xff0c;如下所示是个CTE样例&#xff1a; ​ CTE表达式往往在同一条sql中多次被重复引用&#xff0c;如上图所示的cte被引用了两次&#xff08;c1 和 c2&#xff09;&#xff0c;我们称为2个CTE实例。 ​ 本文只要…

Windows系统Nginx下载安装配置 运行错误处理

Nginx是一款轻量级的web 服务器/反向代理 服务器。本篇文章主要是nginx的下载安装&#xff0c;处理运行中遇到的问题&#xff0c;配置反向代理。主要分为两部分&#xff1a;下载安装和配置。 目录 1.下载安装 2.nginx配置反向代理 1.下载安装 nginx官网&#xff1a;nginx: …

新160个crackme -044-tsrh-crackme

运行分析 提示去除NAG 不去除NAG也能进入主窗口&#xff0c;需要破解Name和Serial PE分析 ASM程序&#xff0c;32位&#xff0c;壳未知 去除NAG ida搜索字符串&#xff0c;发现NAG弹窗标题字符串&#xff0c;双击进入函数 找到了messagebox&#xff0c;即NAG位置00401079 打开x…

网络压缩之动态计算(dynamic computation)

动态计算希望网络可以自由 地调整它需要的计算量。为什么期待网络可以自由地调整它需要的计算量呢? 因为有时候我 们可能同样的模型会想要跑在不同的设备上面&#xff0c;而不同的设备上面的计算资源是不太一样的。所以期待训练好一个网络以后&#xff0c;放到新的设备上面&am…

Python编程基础知识,让编程基础更加扎实(输出个人简介)

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

考研--数学(相关公式)

解析几何 知识点1 A(x1,y1) B(x2,y2) 则AB长度 |AB| A、B中点的坐标 &#xff08;&#xff0c;) 知识点2 方程求解 ①点斜式&#xff1a; y-y0k(x0-x) ②斜率式&#xff1a; ykxb ③两点式&#xff1a; …

【笔记篇】Davinci Configurator CanNm模块

目录 1 简介1.1 架构概览2 功能描述2.1 特性2.2 初始化2.3 状态机2.3.1 网络模式2.3.1.1 重复报文状态2.3.1.2 正常状态2.3.1.3 准备休眠状态2.3.2 预休眠模式2.3.3 总线休眠模式2.4 被动模式(对于被动节点)2.5 NM报文格式2.6 NM报文发送2.6.1 重试第一次报文请求2.7 降低总线…

集成电路学习:什么是I2C内部集成电路总线

I2C&#xff1a;内部集成电路总线 I2C&#xff0c;全称Inter-Integrated Circuit&#xff0c;即内部集成电路总线&#xff0c;是由飞利浦公司&#xff08;现为恩智浦半导体&#xff09;在上世纪八十年代初开发的一种同步的串行通信总线。它以其接线简单、硬件实现容易、可扩展性…

Mysql8利用binlog实现数据恢复

文章目录 1binlog基本概念2 binlog相关常用命令3 binlog工具mysqlbinlog4 测试数据准备&导入数据5 模拟误删表6 数据恢复方式说明7 数据恢复分析(偏移量方式恢复)8 数据恢复9 验证10 数据恢复的局限性11 总结 1binlog基本概念 binlog即binary log&#xff0c;二进制日志文件…

【React原理 - 任务调度之中断恢复】

概览 本文紧接上文介绍React调度的时间分片中任务中断和恢复&#xff0c;由于篇幅过长&#xff0c;所以拆成了两篇。上文主要介绍了调度器中的优先级和调度任务的触发、注册和调度循环。本文主要从任务调度入手介绍调度任务之后发送了什么&#xff0c;即在协调器中如何进行到f…

【matlab】数组操作:寻找最大值和最小值及其位置ind2sub函数

【matlab】数组操作&#xff1a;寻找最大值和最小值及其位置ind2sub函数 本文将介绍如何在MATLAB环境中使用内置函数来创建数组&#xff0c;以及如何找到数组中的最大值和最小值及其对应的位置。通过示例代码&#xff0c;我们将一步步展示这一过程&#xff0c;帮助读者更好地理…

探索Python的测试之道:unittest库的奥秘

文章目录 探索Python的测试之道&#xff1a;unittest库的奥秘背景&#xff1a;为何选择unittest&#xff1f;什么是unittest库&#xff1f;如何安装unittest库&#xff1f;简单库函数使用方法场景应用场景一&#xff1a;测试数学运算场景二&#xff1a;测试异常处理场景三&…

armv8 memory model概述

概述 在armv8 架构中&#xff0c;它引入了更多的维度来描述内存模型&#xff0c;从而在此基础上进行硬件优化(但其中一些并未被主流的软件所接受)&#xff0c;在此做一些简单的整理&#xff0c;更多信息请参考 Arm spec 以及 AMBA 协议。下文主要是对Memory 和 Device 两大类的…