C++常见算法&数据结构模版
各种常见算法 & 数据结构模板
1. 最长不下降子序列(LIS)
1.1 \(O(n^2)\) 做法
点击查看代码
for (int i = 1;i <= n;i++) {cin >> a[i];dp[i] = 1;}for (int i = 1;i <= n;i++) {for (int j = 1;j < i;j++) {if (a[i] > a[j]) {dp[i] = max(dp[i],dp[j] + 1);}}ans = max(ans,dp[i]);}
1.2 \(O(n \log n)\) 做法
点击查看代码
#include <bits/stdc++.h>using namespace std;const int N = 1e5 + 10;int dp[N], n, x, k = 1;int main() {cin >> n >> x;dp[1] = x;for (int i = 2; i <= n; i++) {scanf("%d",&x);if (x > dp[k]) {dp[++k] = x;} else {int p = lower_bound(dp + 1, dp + k + 1, x) - dp;dp[p] = x;}}cout << k;return 0;}
2. 背包问题
2.1 01背包-二维数组
点击查看代码
cin >> maxw >> n;for (int i = 1;i <= n;i++) {cin >> w >> v;for (int j = 1;j <= maxw;j++) {if (w > j) {dp[i][j] = dp[i - 1][j];} else {dp[i][j] = max(dp[i - 1][j],dp[i - 1][j - w] + v);}}}cout << dp[n][maxw];
2.2 01背包-一维数组优化
点击查看代码
cin >> maxv >> n; // maxv: 价值for (int i = 1;i <= n;i++) {cin >> v;for (int j = maxv;j >= v;j--) {dp[j] = max(dp[j],dp[j - v] + v);}}cout << dp[maxv];
2.3 完全背包-一维数组优化
点击查看代码
#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N = 1e4 + 10, S = 1e7 + 10;ll dp[S], vi, wi, maxw, n;int main() {scanf("%lld%lld", &maxw, &n);for (int i = 1; i <= n; i++) {scanf("%lld%lld", &wi, &vi);for (int j = wi; j <= maxw; j++) {dp[j] = max(dp[j], dp[j - wi] + vi);}}printf("%lld", dp[maxw]);return 0;}
2.4 多重背包-普通版本
点击查看代码
#include <iostream>using namespace std;const int N = 110;int dp[N], v, s, w;int n, maxw;int main() {scanf("%d%d", &n, &maxw);for (int i = 1; i <= n; i++) {scanf("%d%d%d", &w, &v, &s);for (int k = 1; k <= s; k++) {for (int j = maxw; j >= w; j--) {dp[j] = max(dp[j], dp[j - w] + v);}}}printf("%d", dp[maxw]);return 0;}
2.5 多重背包-二进制优化版
点击查看代码
#include <iostream>using namespace std;const int N = 2e4 + 10;int dp[2010], v[N], w[N];int n, wi, vi, si, maxw, k;int main() {scanf("%d%d", &n, &maxw);for (int i = 1; i <= n; i++) {scanf("%d%d%d", &wi, &vi, &si);for (int t = 1; t <= si; t *= 2) {k++;v[k] = t * vi;w[k] = t * wi;si -= t;}if (si > 0) {k++;v[k] = si * vi;w[k] = si * wi;}}for (int i = 1; i <= k; i++) {for (int j = maxw; j >= w[i]; j--) {dp[j] = max(dp[j], dp[j - w[i]] + v[i]);}}printf("%d", dp[maxw]);return 0;}
2.6 分组背包
点击查看代码
#include <iostream>using namespace std;const int N = 110;int dp[N], v[N][N], w[N][N], s[N];int n, maxw;int main() {scanf("%d%d", &n, &maxw);for (int i = 1; i <= n; i++) {scanf("%d", &s[i]);for (int j = 1; j <= s[i]; j++) {scanf("%d%d", &w[i][j], &v[i][j]);}}for (int i = 1; i <= n; i++) {for (int j = maxw; j >= 1; j--) {for (int k = 1; k <= s[i]; k++) {if (w[i][k] <= j)dp[j] = max(dp[j], dp[j - w[i][k]] + v[i][k]);}}}printf("%d", dp[maxw]);return 0;}
2.7 二维费用背包
点击查看代码
#include <iostream>using namespace std;const int N = 410;int dp[N][N], maxw, maxv, vi, wi, c;int n;int main() {scanf("%d%d", &maxw, &maxv);cin >> n;for (int i = 1; i <= n; i++) {cin >> wi >> vi >> c;for (int j = maxw; j >= wi; j--) {for (int k = maxv; k >= vi; k--) {dp[j][k] = max(dp[j][k], dp[j - wi][k - vi] + c);}}}cout << dp[maxw][maxv];return 0;}
3. 图论最短路
3.1 朴素Dijkstra
时间复杂度:\(O(n^2)\)
点击查看代码
#include <bits/stdc++.h>using namespace std;const int N = 60;int a[N][N];int d[N];bool f[N];int n,s;int main() {cin >> n >> s;for (int i = 1;i <= n;i++) {for (int j = 1;j <= n;j++) {cin >> a[i][j];}}memset(d,0x3f,sizeof(d)); // 初始化为INFd[s] = 0; // 走到起点的最短路为0for (int i = 1;i <= n;i++) {int mi = -1;// 找到最小数下标for (int j = 1;j <= n;j++) {if (!f[j] && (mi == -1 || d[j] < d[mi])) {mi = j;}}f[mi] = true;// 从最短路的点开始更新最短路for (int j = 1;j <= n;j++) {if (!f[j] && a[mi][j] && a[mi][j] + d[mi] < d[j]) {d[j] = a[mi][j] + d[mi];}}}for (int i = 1;i <= n;i++) {if (i != s) {//走不到 -> 0x3f3f3f3fif (d[i] == 0x3f3f3f3f) cout << -1 << " ";else cout << d[i] << " ";}}return 0;}
3.2 优先队列BFS优化 Dijkstra
时间复杂度:\(O(m \times logm)\)
点击查看代码
#include <bits/stdc++.h>using namespace std;const int N = 1e5 + 10;typedef pair<int,int> PII;struct node{int to,next,len;}a[N];int pre[N],k = 0;int n,m,x,y,len;priority_queue<PII,vector<PII>,greater<PII>> q; // 优先队列void add(int x,int y,int len) { // 建边a[++k] = {y,pre[x],len};pre[x] = k;}bool f[N];int d[N];int main() {scanf("%d%d",&n,&m);for (int i = 1;i <= m;i++) {scanf("%d%d%d",&x,&y,&len);add(x,y,len);}// 初始化q.push({0,1});memset(d,0x3f,sizeof(d));d[1] = 0;while (!q.empty()) {PII h = q.top();int dis = h.first,p = h.second;q.pop();if (f[p]) continue;f[p] = true;if (p == n) { // 走到终点cout << dis;return 0;}for (int i = pre[p];i;i = a[i].next) { // 更新最短路int to = a[i].to;if (a[i].len + dis < d[to]) {d[to] = a[i].len + dis;q.push({a[i].len + dis,to});}}}cout << -1;return 0;}
3.3 Floyd
时间复杂度:\(O(n^3)\)
点击查看代码
#include <bits/stdc++.h>using namespace std;const int N = 110,INF = 0x3f3f3f3f;int d[N][N];int n,m,x,y,l;int main() {cin >> n >> m;memset(d,0x3f,sizeof(d));for (int i = 1;i <= n;i++) d[i][i] = 0;for (int i = 1;i <= m;i++) {cin >> x >> y >> l;d[x][y] = l;}for (int k = 1;k <= n;k++) {for (int i = 1;i <= n;i++) {for (int j = 1;j <= n;j++) {if (d[i][k] != INF && d[k][j] != INF) {d[i][j] = min(d[i][j],d[i][k] + d[k][j]);}}}}for (int i = 1;i <= n;i++) {for (int j = 1;j <= n;j++) {if (d[i][j] == INF) cout << "N ";else cout << d[i][j] << " ";}cout << endl;}return 0;}
4.树
4.1 树的直径
两次深搜求直径:
从树上任意找一个点 \(x\) 搜索离 \(x\) 最远的点 \(u\) ,\(u\) 一定是直径的一个端点;
从直径的一个端点 \(u\) 开始搜索,搜索出离 \(u\) 最远的点 \(v\) ,\(v\) 一定是直径的另一个端点,因此 \(uv\) 一定是直径。
点击查看代码
#include <bits/stdc++.h>using namespace std;const int N = 110;int n,x,y;struct node{int to,next;}a[N * 2];int pre[N];int k = 0;int dep[N];void add(int x,int y) {a[++k] = {y,pre[x]};pre[x] = k;}void dfs(int x,int fath) {dep[x] = dep[fath] + 1;for (int i = pre[x];i;i = a[i].next) {if (a[i].to != fath) {dfs(a[i].to,x);}}}int main() {cin >> n;for (int i = 1;i <= n - 1;i++) {scanf("%d%d",&x,&y);add(x,y);add(y,x);}dfs(1,0);int x = 1;// 求出离1号点最远的那个点for (int i = 2;i <= n;i++) {if (dep[i] > dep[x]) x = i;}dfs(x,0);int y = 1;// 找出离x号点最远的点yfor (int i = 1;i <= n;i++) {if (dep[i] > dep[y]) y = i;}printf("%d",dep[y] - 1);
4.2 树的中心
树的中心指的是,该结点离树中的其他结点,最远距离最近。
树的中心满足如下性质:
(1)它一定在某条树的直径上,且到直径的两端的距离差不超过1。
(2)即使树有多条直径,但树的中心至多有2个,且均为直径的中点。
求树的中心:由于树的中心一定在直径上,求出直径的两个端点 \(u v\),加深 \(v\) 深度更深。
(1) 如果 \(dep[v]\) 是奇数,爬树 \(dep[v]/2\) 次;
(2) 如果 \(dep[v]\) 是偶数,爬树 \(dep[v]/2-1\) 次,得到两个中心的靠下的一个点,另一个点就是该点的父;
点击查看代码
#include <iostream>using namespace std;const int N = 1e5 + 10;int n,x,y;struct node{int to,next;}a[N * 2];int pre[N];int k = 0;int dep[N],fa[N];void add(int x,int y) {a[++k] = {y,pre[x]};pre[x] = k;}void dfs(int x,int fath) {dep[x] = dep[fath] + 1;fa[x] = fath;for (int i = pre[x];i;i = a[i].next) {if (a[i].to != fath) {dfs(a[i].to,x);}}}int main() {cin >> n;for (int i = 1;i <= n - 1;i++) {scanf("%d%d",&x,&y);add(x,y);add(y,x);}dfs(1,0);int x = 1;for (int i = 2;i <= n;i++) {if (dep[i] > dep[x]) x = i;}dfs(x,0);int y = 1;for (int i = 1;i <= n;i++) {if (dep[i] > dep[y]) y = i;}if (dep[y] % 2 == 1) {int d = dep[y] / 2;for (int i = 1;i <= d;i++) {y = fa[y];}printf("%d",y);} else {int d = dep[y] / 2 - 1;for (int i = 1;i <= d;i++) {y = fa[y];}if (y < fa[y]) cout << y << " " << fa[y];else cout << fa[y] << " " << y;}return 0;}
4.3 树的公共祖先(LCA)
解法一:染色法
点击查看代码
#include <iostream>using namespace std;const int N = 1e5 + 10;int n,x,y;struct node{int to,next;}a[N * 2];int pre[N];int k = 0;int dep[N],fa[N];void add(int x,int y) {a[++k] = {y,pre[x]};pre[x] = k;}bool vis[N];void dfs(int x,int fath) {dep[x] = dep[fath] + 1;fa[x] = fath;for (int i = pre[x];i;i = a[i].next) {if (a[i].to != fath) {dfs(a[i].to,x);}}}int main() {cin >> n;int u,v;cin >> u >> v;for (int i = 1;i <= n - 1;i++) {scanf("%d%d",&x,&y);add(x,y);add(y,x);}dfs(1,0);vis[u] = true;while (fa[u] != 0) {u = fa[u];vis[u] = true;}while (!vis[v]) {v = fa[v];}cout << v;return 0;}
解法二:两个结点同时向上移动
思路:
(1)求出每个结点的深度;
(2)如果两个结点重叠,那么得知公共祖先;
(3)如果不重叠,选择深度更大的结点,向父元素移动,重复上述过程,直到重叠。
点击查看代码
#include <iostream>using namespace std;const int N = 1e5 + 10;int n,x,y;struct node{int to,next;}a[N * 2];int pre[N];int k = 0;int dep[N],fa[N];void add(int x,int y) {a[++k] = {y,pre[x]};pre[x] = k;}bool vis[N];void dfs(int x,int fath) {dep[x] = dep[fath] + 1;fa[x] = fath;for (int i = pre[x];i;i = a[i].next) {if (a[i].to != fath) {dfs(a[i].to,x);}}}int main() {cin >> n;int u,v;cin >> u >> v;for (int i = 1;i <= n - 1;i++) {scanf("%d%d",&x,&y);add(x,y);add(y,x);}dfs(1,0);while (u != v) {if (dep[u] > dep[v]) {u = fa[u];} else {v = fa[v];}}cout << u;return 0;
4.4 树的重心
求出每个结点删除后的最大子树的大小,并求出该值的最小值,最后循环看哪些树删除后子树大小==所求的最小值,哪些结点就是重心。
点击查看代码
#include <bits/stdc++.h>using namespace std;const int N = 1e5 + 10;int n,x,y;struct node{int to,next;}a[N * 2];int pre[N];int k = 0;int dep[N],fa[N],si[N];int ma[N];int mi = INT_MAX;void add(int x,int y) {a[++k] = {y,pre[x]};pre[x] = k;}bool vis[N];int dfs(int x,int fath) {dep[x] = dep[fath] + 1;fa[x] = fath;si[x] = 1;for (int i = pre[x];i;i = a[i].next) {if (a[i].to != fath) {si[x] += dfs(a[i].to,x);}}return si[x];}int main() {cin >> n;for (int i = 1;i <= n - 1;i++) {scanf("%d%d",&x,&y);add(x,y);add(y,x);}dfs(1,0);for (int i = 1;i <= n;i++) {ma[i] = n - si[i];for (int j = pre[i];j;j = a[j].next) {if (a[j].to != fa[i]) {ma[i] = max(ma[i],si[a[j].to]);}}mi = min(ma[i],mi);}for (int i = 1;i <= n;i++) {if (ma[i] == mi) {cout << i << " ";}}return 0;}
5.最长公共子序列(LCS)
5.1 \(O(n^2)\) 做法
点击查看代码
#include <iostream>using namespace std;const int N = 1010;int n, dp[N][N], a[N], b[N];int main() {cin >> n;for (int i = 1; i <= n; i++) scanf("%d", &a[i]);for (int i = 1; i <= n; i++) scanf("%d", &b[i]);for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {if (a[i] == b[j]) {dp[i][j] = dp[i - 1][j - 1] + 1;} else {dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);}}}printf("%d", dp[n][n]);return 0;}
5.2 \(O(n \log n)\) 做法
点击查看代码
#include <iostream>using namespace std;const int N = 1e5 + 10;int dp[N], a[N], b[N], n, c[N];int main() {cin >> n;for (int i = 1; i <= n; i++) {cin >> a[i];c[a[i]] = i;}for (int i = 1; i <= n; i++) {cin >> b[i];}dp[1] = c[b[1]];int k = 1;for (int i = 2; i <= n; i++) {if (c[b[i]] > dp[k]) {dp[++k] = c[b[i]];} else {int p = lower_bound(dp + 1, dp + k + 1, c[b[i]]) - dp;dp[p] = c[b[i]];}}printf("%d", k);return 0;}
6. 并查集
6.1 朴素并查集
点击查看代码
int find(int x) {if (x == fa[x]) return x;return find(fa[x]);}
点击查看代码
void merge(int x, int y) {int rx = find(x), ry = find(y);if (rx != ry) fa[rx] = ry;}
6.2 路径压缩
点击查看代码
int find(int x) {if (x == fa[x]) return x;return fa[x] = find(fa[x]);}
7. 最小生成树
7.1 \(Kustral\) 算法
点击查看代码
for (int i = 1;i <= k;i++) {if (find(a[i].x) != find(a[i].y)) {merge(a[i].x, a[i].y);sum += a[i].len;c++;if (c == n - 1) {printf("%d", sum);return 0;}}}
8. 素数筛法
8.1 埃氏筛法
点击查看代码
#include <bits/stdc++.h>using namespace std;const int N = 1e6 + 10;bool f[N];int n, ans;int main() {scanf("%d", &n);f[0] = f[1] = true;for (int i = 2;i <= sqrt(n);i++) {if (!f[i]) {for (int j = i * 2;j <= n;j += i) {if (!f[j]) {f[j] = true;}}}}for (int i = 1; i <= n; i++) {if (!f[i]) ans++;}printf("%d", ans);return 0;}
8.2 欧拉筛法
点击查看代码
f[0] = f[1] = true;for (int i = 2;i <= e;i++) {if (!f[i]) primes[++k] = i;for (int j = 1;i * primes[j] <= e;j++) {f[i * primes[j]] = true;if (i % primes[j] == 0) break;}}
C++常见算法&数据结构模版的更多相关文章
- acm常见算法及例题
转自:http://blog.csdn.net/hengjie2009/article/details/7540135 acm常见算法及例题 初期:一.基本算法: (1)枚举. (poj17 ...
- 经典面试题(二)附答案 算法+数据结构+代码 微软Microsoft、谷歌Google、百度、腾讯
1.正整数序列Q中的每个元素都至少能被正整数a和b中的一个整除,现给定a和b,需要计算出Q中的前几项, 例如,当a=3,b=5,N=6时,序列为3,5,6,9,10,12 (1).设计一个函数void ...
- 算法数据结构 | 只要30行代码,实现快速匹配字符串的KMP算法
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是算法数据结构专题的第29篇文章,我们来聊一个新的字符串匹配算法--KMP. KMP这个名字不是视频播放器,更不是看毛片,它其实是由Kn ...
- Hadoop学习笔记—12.MapReduce中的常见算法
一.MapReduce中有哪些常见算法 (1)经典之王:单词计数 这个是MapReduce的经典案例,经典的不能再经典了! (2)数据去重 "数据去重"主要是为了掌握和利用并行化思 ...
- [Machine Learning] 机器学习常见算法分类汇总
声明:本篇博文根据http://www.ctocio.com/hotnews/15919.html整理,原作者张萌,尊重原创. 机器学习无疑是当前数据分析领域的一个热点内容.很多人在平时的工作中都或多 ...
- 常见算法是js实现汇总(转载)
常见算法是js实现汇总 /*去重*/ <script> function delRepeat(arr){ var newArray=new Array(); var len=arr.len ...
- paper 12:机器学习常见算法分类汇总
机器学习无疑是当前数据分析领域的一个热点内容.很多人在平时的工作中都或多或少会用到机器学习的算法.这里南君先生为您总结一下常见的机器学习算法,以供您在工作和学习中参考. 机器学习的算法很多.很多时候困 ...
- AI - 机器学习常见算法简介(Common Algorithms)
机器学习常见算法简介 - 原文链接:http://usblogs.pwc.com/emerging-technology/machine-learning-methods-infographic/ 应 ...
- 前端常见算法的JS实现
1.冒泡排序 function bubbleSort(arr){ var i = 0, j = 0; for(i=1; i<arr.length; i++){ for(j=0; j<=ar ...
- Java 中常见的数据结构
1.数据结构有什么作用? 当使用 Java 里面的容器类时,你有没有想过,怎么 ArrayList 就像一个无限扩充的数组,也好像链表之类的.很好使用,这就是数据结构的用处,只不过你在不知不觉中使用了 ...
随机推荐
- Tauri-Admin通用后台管理系统|tauri+vue3+pinia桌面端后台EXE
基于tauri+vite4+pinia2跨端后台管理系统应用实例TauriAdmin. tauri-admin 基于最新跨端技术 Tauri Rust webview2 整合 Vite4 构建桌面端通 ...
- 现代C++(Modern C++)基本用法实践:四、模板
概述 C++的模板是泛型编程思想的一种实现.C++是强类型语言,处处强调类型.同样的加法运算,int和float的加法运算需定义两个函数(重载),而使用模板则可以只用一个函数(见下面示例). 这类似我 ...
- C# 12新预览功能介绍
Visual Studio 17.7 Preview 3和.NET 8 Preview 6延续了C# 12的发展.该预览版包含的功能旨在为未来的性能增强奠定基础.对内联数组的轻松访问将允许库在更多地方 ...
- PDF书签的编辑器,基于(python、Tkinter)
使用 脚本 在github下载源码. 安装python3 安装必要的python包 pip install numpy pip install pandas pip install PyMuPDF p ...
- ranger2.1.0源码编译以及安装
ranger2.1.0源码编译以及安装 编译环境准备 环境需求 示例版本 JDK8 Java(TM) SE Runtime Environment (build 1.8.0_231-b11) mave ...
- 探索Java通信面试的奥秘:揭秘IO模型、选择器和网络协议,了解面试中的必备知识点!
了解常见的TCP/UDP TCP(Transmission Control Protocol)是一种面向连接的可靠的传输协议.类似于打电话,它通过建立一个连接和保证数据的可靠传输来提高通信的可靠性.然 ...
- Module build failed: TypeError: this.getOptions is not a function at Object.loader
这个问题主要是因为node-loader版本过高导致的问题 解决方案 css-loader降为3.6.0版本即可 npm install css-loader@2.0.2 --save-dev npm ...
- CF1601 题解
偶然看这一场的题目,忽然很有感觉,于是写了一下 A 题面 考虑每一位可以单独分开考虑 考虑单独的一位,每次要选 \(m\) 个位置,可能产生贡献的位置就是这位为 1 的数,设数量为 \(x\),则 \ ...
- cesium 绑定dom弹窗(跟随模型)
https://blog.csdn.net/qq_36266612/article/details/109648367?utm_term=cesium%E6%80%8E%E4%B9%88%E6%B7% ...
- 部署安装maven和mvnd
前言 maven是常见的java构建工具,优点是稳定可靠,缺点是构建太慢,maven-mvnd是maven的强化版,致力于提高构建速度,默认情况下,mvnd 使用多核CPU并行构建. 常见的java构 ...