算法基础课-搜索与图论

news2024/10/7 11:26:25

DFS

题目链接:842. 排列数字 - AcWing题库
思路:写的很好的题解AcWing 842. 排列数字--深度优先遍历代码+注释 - AcWing

#include<bits/stdc++.h>

using namespace std;
int n;
int st[10];
vector<int> a;
void dfs(){
    if(a.size() == n){
        for(int i=0;i<n;i++){
            cout<<a[i]<<" ";
        }
        cout<<endl;
    }
    for(int i=1;i<=n;i++){
        if(!st[i]){
            
            a.push_back(i);
            st[i] = true;
            dfs();
            a.pop_back();
            st[i] = false;
            
        }
    }
}

int main()
{
    cin>>n;
    dfs();
    
    return 0;
}

也可以考虑使用c++自带的next_permutation函数直接秒了:

#include<bits/stdc++.h>
using namespace std;
vector<int> a;
int n;
int st[10];

int main(){
	cin>>n;
	for(int i=0;i<n;i++) st[i] = i+1;
	do{
		for(int i=0;i<n;i++) cout<<st[i]<<" ";
		cout<<endl;
	}while(next_permutation(st,st+n));
	return 0;
} 

BFS

题目链接:844. 走迷宫 - AcWing题库

思路:由于bfs是一层一层扩展,所以能保证走到终点时,走过的距离最短,所以不需要取min。可以在bfs中判断一下,走到终点直接输出终点的distance。

#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair<int,int> PII;
int n,m;
const int N = 110;
int g[N][N];
int dist[N][N];
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
// int st[N][N];
void bfs(int x,int y){
    queue<PII> q;
    q.push({x,y});
    dist[0][0] = 0;
    // st[x][y] = true;
    while(q.size()){
        auto t = q.front();
        q.pop();
        int x = t.x,y = t.y;
        for(int i=0;i<4;i++){
            int tx = x + dx[i];
            int ty = y + dy[i];
            if(g[tx][ty] == 1) continue;
            if(tx<0||tx>=n||ty<0||ty>=m) continue;
            // if(st[tx][ty]) continue;
            // st[tx][ty] = true;
            g[tx][ty] = 1;
            dist[tx][ty] = min(dist[tx][ty],dist[x][y]+1);
            q.push({tx,ty});
            // cout<<tx<<" "<<ty<<endl;
        }
    }
}
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++) cin>>g[i][j];
    }
    memset(dist,0x3f,sizeof dist);
    bfs(0,0);
    cout<<dist[n-1][m-1];
    return 0;
}

树与图的深度优先遍历

题目链接:1207. 大臣的旅费 - AcWing题库

思路:题意是求树的直径(树中两个最远结点的距离),可以随机找一个点0,走到距离0点最远的点1,再从这个点1走到距离点1最远的点2,此时点1距离点2的距离就是树的直径。

图的存储与遍历参考:B02 图的存储_哔哩哔哩_bilibili

#include<bits/stdc++.h>
#define x first 
#define y second 

using namespace std;
const int N = 100010;
typedef pair<int,int> PII;
vector<PII> h[N];
int dist[N];
void dfs(int u,int father,int distance){
    dist[u] = distance;
    
    for(auto t:h[u]){
        if(t.x!=father){
            dfs(t.x,u,distance+t.y);
        }
    }
    
}

int main(){
    int n ;
    cin>>n;
    for(int i=0;i<n-1;i++){
        int x,y,d;
        cin>>x>>y>>d;
        h[x].push_back({y,d});
        h[y].push_back({x,d});
    }
    
    dfs(1,-1,0);
    int u = 1;
    for(int i=1;i<=n;i++){
        if(dist[i]>dist[u]){
            u = i;
        }
    }
    dfs(u,-1,0);
    for(int i=1;i<=n;i++){
        if(dist[i]>dist[u]){
            u = i;
        }
    }
    
    int s = dist[u];

    printf("%lld\n", s * 10 + s * (s + 1ll) / 2);

    return 0;
}

树与图的广度优先遍历

题目链接:847. 图中点的层次 - AcWing题库

思路:h数组表示邻接表,下标表示结点编号,每个vector存储的是每个结点能到达的节点。

这个老师讲的超级好。B02 图的存储_哔哩哔哩_bilibili

#include<bits/stdc++.h>

using namespace std;
const int N = 100010;
vector<int> h[N];
bool st[N];
int dist[N];
int n,m;
void bfs(int u){
    queue<int> q;
    q.push(u);
    st[u] = true;
    dist[u] = 0;
    while(q.size()){
        int t = q.front();
        q.pop();
        if(t == n){
            cout<<dist[t];
            return;
        }
        for(int i=0;i<h[t].size();i++){
            int ne = h[t][i];
            if(st[ne]) continue;
            
            st[ne] = true;
            q.push(ne);
            dist[ne] = dist[t] + 1;
        }
    }
    cout<<-1<<endl;
    return;
}
int main(){
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int a,b;
        cin>>a>>b;
        h[a].push_back(b);
    }
    memset(dist,-1,sizeof dist);
    bfs(1);
    return 0;
}

拓扑排序

题目链接:848. 有向图的拓扑序列 - AcWing题库
思路:跟bfs有些相似,先找入度为零的点加入到队列当中,再枚举当前结点出边,减少出边元素的入度,当入度为0时加入到拓扑序列中,这里是当出队的时候加入到序列中,跟bfs更像了。

这个老师讲的可好D01 拓扑排序_哔哩哔哩_bilibili。

#include<bits/stdc++.h>

using namespace std;
const int N = 100010;
vector<int> e[N],tp;
int din[N];

int n,m;
bool topsort(){
    queue<int> q;
    for(int i=1;i<=n;i++){
        if(din[i] == 0) q.push(i);
    }
    while(q.size()){
        auto t = q.front();
        q.pop();
        tp.push_back(t);
        for(auto y : e[t]){
            din[y]--;
            if(!din[y]) q.push(y);
        } 
    }
    return tp.size() == n;
}

int main(){
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int a,b;
        cin>>a>>b;
        e[a].push_back(b);
        din[b]++;
    }
    if(topsort()){
        for(int i = 0;i<n;i++){
            cout<<tp[i]<<" ";
        }
    }else cout<<-1<<endl;
    
    return 0;
}

Dijkstra

朴素版

题目链接:849. Dijkstra求最短路 I - AcWing题库
思路:采取贪心的策略,对当前能到达的路径最短的点,使用其进行更新距离操作。

D02 最短路 Dijkstra 算法_哔哩哔哩_bilibili

#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair<int,int> PII;
const int N = 510;
const int M = 1e5+10;
vector<PII> e[N];
int dist[N];
int n,m;
bool st[N];
void dijkstra(int s){
    dist[s] = 0;
    
    for(int i=1;i<n;i++){
        int u = 0;
        for(int i=1;i<=n;i++){
            if(!st[i]&&(dist[i]<dist[u] || u == 0)) u = i;
        }
        // cout<<u<<endl;
        st[u] = true;
        for(auto pr : e[u]){
            int v = pr.x, w = pr.y;
            if(dist[v]>dist[u]+w){
                dist[v] = dist[u] + w;
            }
        }
    }
}

int main(){
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int a,b,w;
        cin>>a>>b>>w;
        e[a].push_back({b,w});
    }
    memset(dist,0x3f,sizeof dist);
    dijkstra(1);
    if(dist[n] == 0x3f3f3f3f) cout<<-1<<endl;
    else cout<<dist[n]<<endl;
    return 0;
}

堆优化版本

题目链接:850. Dijkstra求最短路 II - AcWing题库

思路:每次选秀选出当前最小的点,朴素版需要遍历寻找,堆优化版使用优先队列维护当前没有遍历到的距离最小的点,将每次选秀的遍历替换成取队列头部元素,从而降低时间复杂度。

需要注意的是为了维护优先队列中的顺序,存储的距离为负数。

D02 最短路 Dijkstra 算法_哔哩哔哩_bilibili

#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
int n,m;
typedef pair<int,int> PII;
const int N = 150010, M = 150010;
int dist[N];
priority_queue<PII> q;
vector<PII> h[N];
bool st[N];
void dijkstra(int s){
    dist[s] = 0;
    q.push({0,s});
    while(q.size()){
        PII p = q.top();
        int u = p.y;
        q.pop();
        if(st[u]) continue;
        st[u] = true;
        for(auto t : h[u]){
            int v = t.x, w = t.y;
            if(dist[v]>dist[u] + w){
                dist[v] = dist[u] + w;  //忘记更新距离
                q.push({-(dist[u]+w),v});
            }
        }
        
    }
}
int main(){
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        h[a].push_back({b,c});
    }
    memset(dist,0x3f,sizeof dist);
    dijkstra(1);
    if(dist[n] == 0x3f3f3f3f) cout<<-1<<endl;
    else cout<<dist[n]<<endl;
    return 0;
}

bellman-ford

spfa

Floyd

题目链接:854. Floyd求最短路 - AcWing题库

思路:D04 最短路 Floyd 算法_哔哩哔哩_bilibili

#include<bits/stdc++.h>
using namespace std;
const int N = 210,INF = 1e9;
int n,m,Q;
int d[N][N];
void floyd(){
	for(int k=1;k<=n;k++){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				d[i][j] = min(d[i][j],d[i][k]+d[k][j]);
			}
		}
	}
}
int main(){
	cin>>n>>m>>Q;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(i==j) d[i][j] = 0;
			else d[i][j] = INF;
		}
	}	
	while(m--){
		int a,b,c;
		cin>>a>>b>>c;
		d[a][b] = min(d[a][b],c);
	}
	floyd();
	while(Q--){
		int a,b;
		cin>>a>>b;
		int t = d[a][b];
		if(t>INF/2) cout<<"impossible"<<endl;
		else cout<<t<<endl;
	}
	return 0;
}

Prim

题目链接:858. Prim算法求最小生成树 - AcWing题库

思路:D07 最小生成树 Prim 算法_哔哩哔哩_bilibili

和dijkstra一样,n次循环,每次选取最近的点来更新距离。

#include<bits/stdc++.h>
using namespace std;
const int N = 510,INF = 0x3f3f3f3f;
int n,m;
int g[N][N];
int dist[N];
bool st[N];
int prim(){
	memset(dist,0x3f,sizeof dist);
	int res = 0;
	for(int i=0;i<n;i++){
		int t = -1;
		for(int j=1;j<=n;j++){
			if(!st[j]&&(t==-1||dist[t]>dist[j]))
				t = j;
		}
		if(i && dist[t]==INF) return INF;
		if(i) res += dist[t];
		st[t] = true;
		for(int j=1;j<=n;j++) dist[j] = min(dist[j],g[t][j]);
	}
	return res;
}

int main(){
	cin>>n>>m;
	memset(g,0x3f,sizeof g);
	while(m--){
		int a,b,c;
		cin>>a>>b>>c;
		g[a][b] = g[b][a] = min(g[a][b],c);
	}
	int t = prim();
	if(t==INF) cout<<"impossible"<<endl;
	else cout<<t<<endl;
	return 0;
}

Kruskal

题目链接:859. Kruskal算法求最小生成树 - AcWing题库

思路:Kruskal算法是根据边求取最小生成树,先按边权排序,依次取权重最小的边,查看边的起点和终点是否在同一集合中(使用并查集),若不在同一集合,则将边加入到答案中,若在同一集合则继续循环。D08 最小生成树 Kruskal 算法_哔哩哔哩_bilibili

需要注意的是重载小于号的操作要记一下。

#include<bits/stdc++.h>
// #define x first
// #define y second
using namespace std;
// typedef pair<int,int> PII;
int n,m;
const int N = 1e5+10,M = 2e5+10;
struct edge{
    int u;int v;int w;
    bool operator<(const edge &t)const{
        return w<t.w;
    }
}e[M];
// vector<edge> e;
int fa[N];
int find(int x){
    if(x == fa[x]) return x;
    return fa[x] = find(fa[x]);
}
int main(){
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        e[i] = {a,b,c};
    }
    int ans = 0;
    int cnt = 0;
    sort(e,e+m);
    for(int i=1;i<=n;i++) fa[i] = i;
    for(int i=0;i<m;i++){
        int u = e[i].u;
        int v = e[i].v;
        int w = e[i].w;
        if(find(u)!=find(v)){
            ans += w;   
            fa[find(u)] = find(v);
            cnt++;
        }
    }
    if(cnt == n-1) cout<<ans<<endl;
    else cout<<"impossible"<<endl;
    
    return 0;
}

染色法判定二分图

题目链接:860. 染色法判定二分图 - AcWing题库
思路:二分图的意思是看是否有能将所有节点分成两块,每块的节点中不能直接相连这样的情况存在。如下图中的1,4和2,3,5。根据定理:二分图中不存在奇环,我们可以由此判别一个图是否是二分图。D24 二分图判定 染色法_哔哩哔哩_bilibili

老师使用的是链式前向星存储的图结构,具体思路如下。感觉直接用邻接表存储更好想,也更简便。

#include<bits/stdc++.h>

using namespace std;
int n,m;
const int N = 100010,M = 100010;
vector<int> h[N];
int color[N];
bool dfs(int u,int c){
    color[u] = c;
    for(auto t : h[u]){
        if(!color[t]){
            if(dfs(t,3-c)) return 1;
        }else if(color[t] == c) return 1;
    }
    return 0;
}

int main(){
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int a,b;
        cin>>a>>b;
        h[a].push_back(b);
        h[b].push_back(a);
    }
    bool flag = false;
    for(int i =1;i<=n;i++){
        if(!color[i]){
            if(dfs(i,1)){
                flag = 1;
                break;
            }
        }
    }
    if(flag) puts("No");
    else puts("Yes");
    return 0;
    
}

匈牙利算法

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

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

相关文章

Vue 有哪些常用的指令

目录 1. 指令 v-html 1.1. 作用 1.2. 语法 1.3. 练习 2. 指令 v-show 2.1. 作用 2.2. 语法 3. 原理 4. 场景 3. 指令 v-if 3.1. 作用 3.2. 语法 3.3. 原理 3.4. 场景 4. 指令 v-else与 v-else-if 4.1. 作用 4.2. 语法 4.3. 注意 4.4. 使用场景 5. 指令 v-on 5…

详解 Redis 在 Centos 系统上的安装

文章目录 详解 Redis 在 Centos 系统上的安装1. 使用 yum 安装 Redis 52. 创建符号链接3. 修改配置文件4. 启动和停止 Redis 详解 Redis 在 Centos 系统上的安装 1. 使用 yum 安装 Redis 5 如果是Centos8&#xff0c;yum 仓库中默认的 redis 版本就是5&#xff0c;直接 yum i…

Pytorch转onnx

pytorch 转 onnx 模型需要函数 torch.onnx.export。 def export(model: Union[torch.nn.Module, torch.jit.ScriptModule, torch.jit.ScriptFunction],args: Union[Tuple[Any, ...], torch.Tensor],f: Union[str, io.BytesIO],export_params: bool True,verbose: bool False…

深入浅出 -- 系统架构之负载均衡Nginx环境搭建

引入负载均衡技术可带来的收益&#xff1a; 系统的高可用&#xff1a;当某个节点宕机后可以迅速将流量转移至其他节点。系统的高性能&#xff1a;多台服务器共同对外提供服务&#xff0c;为整个系统提供了更高规模的吞吐。系统的拓展性&#xff1a;当业务再次出现增长或萎靡时…

【Java网络编程】HTTP超文本传输协议

一、HTTP超文本传输协议 HTTP全称为Hyper Text Transfer Protocol超文本传输协议&#xff0c;它是基于TCP传输协议构建的应用层协议&#xff0c;作为支撑万维网www的核心协议&#xff0c;为了保证其效率及处理大量事务的能力&#xff0c;因此在设计时&#xff0c;HTTP被制定成为…

前端学习笔记:display(未完成)

这是本人学习的总结&#xff0c;主要学习资料如下 目录 1、一般属性2、flex系列2.1、flex容器的维度2.2、flex其他的关联属性 – 1、一般属性 display是css中的一个重要属性&#xff0c;它的值基本决定了元素的布局。这里就对它的值如何影响元素布局做一个总结。 display:bl…

go | gin 重定向路由重定向

web 重定向 重定向有一点要注意&#xff0c;重定向是在客户端那边执行的&#xff0c;一次服务器只能响应一次请求。但是要注意路由重定向 路由重定向是在服务器内部完成重定向资源请求 package mainimport ("github.com/gin-gonic/gin""fmt" )/* func main…

HUD抬头显示器阳光倒灌实验一般步骤

概述 汽车HUD&#xff08;Head-Up Display&#xff0c;即抬头显示器&#xff09;阳光倒灌实验是一种用于评估汽车抬头显示器在阳光直射条件下显示效果的测试。该实验的目的是确保HUD系统在强烈的阳光下依然能够清晰地显示信息&#xff0c;不影响驾驶员的视线和驾驶安全。 一般…

数据结构---顺序表实现

目录 1.顺序表 2.动态顺序表的实现 &#xff08;4&#xff09;顺序表初始化 &#xff08;5&#xff09;顺序表销毁 &#xff08;6&#xff09;顺序表的插入 a.尾插 b.头插 &#xff08;7&#xff09;顺序表的删除 a.尾删 b.头删 &#xff08;8&#xff09;指定位置之…

jenkins插件集成api使用

jenkins配置插件&api使用 jenkins https://mirrors.jenkins.io/war-stable/2.222.1/ 包下载地址 jenkins镜像源修改 sed -i s/https:\/\/www.google.com/https:\/\/www.baidu.com/g default.json sed -i s/https:\/\/updates.jenkins.io\/download/https:\/\/mirrors.…

使用YOLOv8训练自己的【目标检测】数据集

文章目录 1.收集数据集1.1 使用开源已标记数据集1.2 爬取网络图像1.3 自己拍摄数据集1.4 使用数据增强生成数据集1.5 使用算法合成图像 2.标注数据集2.1确认标注格式2.2 开始标注 3.划分数据集4.配置训练环境4.1获取代码4.2安装环境 5.训练模型5.1新建一个数据集yaml文件5.2预测…

ASP.NET Core 模型绑定

&#x1f340;介绍 在C#中&#xff0c;特别是在ASP.NET Core中&#xff0c;模型绑定是一个将HTTP请求中的数据映射到C#对象的过程。它使得开发者能够方便地从请求中提取数据&#xff0c;而无需手动解析请求体、查询字符串、路由数据等。ASP.NET Core提供了多种特性&#xff08…

《债务与国家的崛起》西方民主制度的金融起源 - 三余书屋 3ysw.net

债务与国家的崛起&#xff1a;西方民主制度的金融起源 你好&#xff0c;今天我们来聊聊由英国知名经济与金融历史学家詹姆斯麦克唐纳所著的《债务与国家的崛起》这本书。19世纪世界历史上发生了一次巨变&#xff0c;即“大分流”。当时西方通过工业革命实现了科技和经济的飞速…

如何保护大模型API安全

大模型的崛起正在改变着我们对机器学习和人工智能的理解&#xff0c;它们不仅提供了令人惊叹的预测和分析能力&#xff0c;还在各行各业的应用中发挥着重要作用。通过提供 API&#xff0c;用户无需了解底层实现细节&#xff0c;使大型模型能够更好地与用户和应用程序进行交互&a…

深度学习相关知识

一.环境配置 1.cuda/cudnn安装&#xff1a; 安装cuda之前首先安装vs&#xff0c;vs版本从低到高安装。 a) 安装cuda&#xff1a;首先查看显卡支持的最高CUDA的版本&#xff0c;以便下载对应的CUDA安装包&#xff1b; cmd命令行&#xff1a;nvidia-smi,显示如下&#xff1a;…

【GPT-4 Turbo】、功能融合:OpenAI 首个开发者大会回顾

GPT-4 Turbo、功能融合&#xff1a;OpenAI 首个开发者大会回顾 就在昨天 2023 年 11 月 6 日&#xff0c;OpenAI 举行了首个开发者大会 DevDay&#xff0c;即使作为目前大语言模型行业的领军者&#xff0c;OpenAI 卷起来可一点都不比同行差。 OpenAI 在大会上不仅公布了新的 …

基于单片机多模式多样式跑马灯系统仿真设计

**单片机设计介绍&#xff0c;基于单片机多模式多样式跑马灯系统仿真设计 文章目录 一 概要二、功能设计三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机多模式多样式跑马灯系统仿真设计是一个集硬件仿真、软件编程和灯光控制于一体的综合性项目。以下是对该设…

Quantinuum与微软携手突破:开创容错量子计算新纪元

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

SystemC入门之测试平台编写完整示例:带同步输出的多路选择器

内容&#xff1a;SystemC入门书中的简单测试平台编写示例。 模块文件编写 带锁存输出的4选1多路器模型。输出在信号clock的正跳变沿时刻被锁存。 sync_mux41.h文件 #include <systemc.h>SC_MODULE(sync_mux41) {sc_in<bool> clock, reset;sc_in<sc_uint<…

【开源语音项目OpenVoice](一)——实操演示

目录 一、前菜 1、Python选择 2、pip源切换 3、ffmpeg配置问题 4、VSCode添加Jupyter扩展 二、配置虚拟环境 1、下载源码 方法一 直接下载源码压缩包 方法二 使用git 1&#xff09;git加入鼠标右键 2&#xff09;git clone源码 2、VSCode出场 1&#xff09;创建pyth…