树和图论【详细整理,简单易懂!】(C++实现 蓝桥杯速查)

树和图论

树的遍历模版
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>  // 添加queue头文件  
using namespace std;const int MAXN = 100;  // 假设一个足够大的数组大小
int ls[MAXN], rs[MAXN];  // 定义左右子树数组//后序遍历
void dfs(int x) {if(ls[x]) dfs(ls[x]);if(rs[x]) dfs(rs[x]);cout << x << ' ';
}//层序遍历
void bfs() {queue<int> q;//起始节点入队q.push(1);//队列不为空则循环while(q.size()) {//访问队列元素xint x = q.front();//取出队列元素q.pop();//一系列操作cout << x << " ";if(ls[x]) q.push(ls[x]);if(rs[x]) q.push(rs[x]);}
}
int main() {int n;cin >> n;for(int i = 1; i <= n; i++) {cin >> ls[i] >> rs[i];}dfs(1);cout << endl;bfs();return 0;
}
最近公共祖先LCA

本质是一个dp,类似于之前的ST表

fa[i][j]表示i号节点,向上走2^j所到的节点,当dep[i]-2^j>=1fa[i][j]有效

又因为我们知道2^(j-1) + 2^(j-1)= 2^j, i的2^(j-1) 级祖先的2^(j-1)级祖先 就是i的2^j级祖先。

形象理解:

我们要求x(5号节点)与y(10号节点)的 LCA

倍增的时候,我们发现y的深度比x的深度要小,于是现将y跳到8号节点,使他们深度一样:

这个时候,x和y的深度就相同了,于是我们按倍增的方法一起去找LCA

我们知道n(10)之内最大的二的次方是8,于是我们向上跳8个单位,发现跳过了。

于是我们将8/2变成4,还是跳过了。

再将4/2变成2,跳到了0号节点。

虽然这时跳到了LCA,但是如果直接if(x==y)就确定的话,程序无法判断是刚好跳到了还是跳过了,应为跳过了x也等于y

于是我们需要刚好跳到LCA的儿子上,然后判断if(x的爸爸==y的爸爸)来确定LCA

由于每一个数都可以分解为几个2^n的和(不信自己试),所以他们一定会跳到LCA的儿子上

于是我们就找到了LCA啦!

代码模版:
int lca(int x,int y){//x喜欢跳。。。//如果x深度比y小,交换x和y 保证x深度大if(dep[x]<dep[y]) swap(x,y); //贪心:i从大到小 //x向上跳的过程中,保持dep[x]>=dep[y],深度不能超过y for(int i=20;i>=0;i--){if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];} //x跳完 此刻x和y的dep相同//如果发现相遇了 那么就是这个点if(x==y) return x;//(int)(log(n)/log(2))就是n以内最大的2的次方,从最大的开始倍增for(int i=(int)(log(n)/log(2));i>=0;i--) //如果x和y爸爸不想同 则没有找到//整个跳跃过程中,保持x!=y,不用x=y判断if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];//x和y一起向上跳 return fa[x][0];//返回他们的爸爸,即是LCA  
}

可是在写LCA之前,我们还得进行预要处理些什么呢?

1.每一个点的深度,以便到时候判断

2.每一个点2^i级的祖先,以便到时候倍增跳

于是我们用一个dep数组来记录每一个点的深度,再用一个fa[i][j]表示节点i的2^j级祖先

void dfs(int x,int p){dep[x]=dep[p]+1;//x的深度是他父亲的深度+1 fa[x][0]=p;//2^0是1,x向上一个的祖先就是他爸爸for(int i=1;i<=20;i++)	fa[x][i]=fa[fa[x][i-1]][i-1];//父节点再向上2^i-1 for(const auto &y : g[x]){ //枚举x所有儿子if(y==p) continue;//如果不是他爸爸 继续dfsdfs(y,x);} 
}
树的重心

指对于某个点,将其删除后,可以是的剩余联通块的最大值最小的点(剩余的若干子树的大小最小)

性质:
  • 中心若干棵子树大小一定**<=n/2**;除了重心以外的所有其他节点,都必然存在一棵节点个数>n/2的子树
  • 一棵树至多两个重心,如果存在,则必然相邻;将连接两个重心的边删除后,一定划分为两棵大小相等的树
  • 树中所有点到某个点的距离和中,到重心的距离和是最小的
  • 两棵树通过一条边相连,重心一定在较大的一棵树一侧的连接点与原重心之间的简单路径上。两棵树大小相同,则重心就是两个连接点。
如何求解重心?

跑一遍dfs,如果mss[x]<=n/2,则x是重心,反之不是。

void dfs(int x,int fa){//初始化mss/sz数组sz[x]=1,mss[x]=0;for(const auto& y:g[x]){if(y==fa) continue;dfs(y,x);sz[x]+=sz[y];mss[x]=max(mss[x],sz[y]);}//后序位置比较mss大小并判断mss[x]=max(mss[x],n-sz[x]);if(mss[x]<=n/2) v.push_back(x);
}
树的直径

树上任意两节点之间最长的简单路径即为树的「直径」。

直径由u,v决定,若有一条直径(u,v)满足 : **1)**u和v度数均为1;2)在任意一个点为根的树上,u和v中必然存在一个点作为最深的叶子节点

如何求解直径?

跑两遍dfs:以任意节点为根的树上跑一次dfs求所有点的深度,选最大的点作为u,再以u为根拍一次dfs,最深的点为v,路径上点的个数为树的dep[v]+1(根节点深度为0)/ dep[v](根节点深度为1)

树上差分
差分的思想方法

如果有一个区间内的权值发生相同的改变的时候,我们可以采用差分的思想方法,而差分的思想方法在于不直接改变区间内的值,而是改变区间[ L , r ] 对于 区间 [ 0, L - 1 ] & 区间[ r + 1, R]的 相对大小关系

差分,可以当做前缀和的逆运算。既然是逆运算,运算方法自然就是相反的了。定义差分数组
d i f f i = a i − a i − 1 diff_i=a_i-a_{i-1} diffi=aiai1

compare:
原数列94759
前缀和913202534
差分数组9-53-24
前缀和的差分数组94759
查分数组的前缀和94759

树上差分,就是利用差分的性质,对路径上的重要节点进行修改(而不是暴力全改),作为其差分数组的值,最后在求值时,利用dfs遍历求出差分数组的前缀和,就可以达到降低复杂度的目的。

这里差分的优点就非常明显了:

  • 算法复杂度超低
  • 适用于一切 连续的 “线段”

这里所谓的线段可以是一段连续的区间,也可以是路径

点差分:

模版题目:给出一棵 n 个点的树,每个点点权初始为 0,现在有 m 次修改,每次修改给出 x,y,将 x,y 简单路径上的所有的点权 +d,问修改完之后每个点的点权。

将序列差分转移到树上:比如我们要对 x,y 的路径上的点统一加上 d。
在这里插入图片描述

涉及到的点有:x,h,b,f,y因此对于点 a 我们不能有影响,操作方案就是 b(回溯时左右加了两次)的点权减去 d,a 的点权减去 d。

最后我们对整棵树做一遍 dfs,将所有点的点权变为其子树(含自己)内所有点的点权,这个操作仿照求每个点子树的 Size 就可以完成了。

模版代码:

同样需要lca的两个模版函数,并添加:

dlt[i]:存放每个点经过的次数

void dfs1(int x){for(int i=0;i<v[x].size();i++){int u=v[x][i];if(u!=fa[x][0]){dfs1(u);//回溯dlt[x]+=dlt[u];}}return;
}
int main() {cin>>n>>k;maxx=log2(n); for(int i=1;i<n;i++){int a,b;cin>>a>>b;v[a].push_back(b),v[b].push_back(a); }dfs(1,0);//k次询问 处理k条路径 for(int i=1;i<=k;i++){int a,b;cin>>a>>b;dlt[a]++,dlt[b]++;int c=lca(a,b);dlt[c]--,dlt[fa[c][0]]--;}dfs1(1);for(int i=1;i<=n;i++) cout<<dlt[i]<<" ";return 0;
}
美妙的例题:

[P3258 JLOI2014] 松鼠的新家 - 洛谷 (luogu.com.cn)

边差分:

模版题目:给出一棵 n个点的树,每条边边权初始为 0,现在有 m 次修改,每次修改给出 x,y将 x,y简单路径上的所有边权 +d,问修改完之后每条边的边权。

首先我们需要一种叫做**“边权转点权”的方法,就是对于每个点我们认为其点权代表这个点与其父节点之间的边的边权**,对于每条边我们认为其边权是这条边所连两个点中深度较大的点的点权,根节点点权无意义。

还是修改 x,y路径上的边,还是这张图:

在这里插入图片描述

涉及的边/点:x,h,f,y,对于点 b 我们不能有影响,操作方案就是 b(回溯时左右加了两次 实则不变)的点权(b与父亲节点的边权)减去 2d。

同样的做完之后一遍 dfs 求一下每个点的点权即可。

图的遍历模版
DFS:
bitset<N> vis;//vis[i]=true说明i点已经走过
void dfs(int x){vis[x]=true;for(const auto& y:g[x]){if(vis[y]) continue;dfs(y);}
}
BFS:

维护一个queue,通常用于求边权相等情况下的最短距离

bitset<N> vis;
queue<int> qu;
void bfs() {  qu.push(1);//从1开始while (!qu.empty()) {  int x = qu.front();  qu.pop();  if (vis[x]) continue;  // 避免重复处理  vis[x] = true;         // 标记已访问  for (const auto& y : g[x]) {  if (!vis[y]) qu.push(y);    // 未访问的邻居入队  }  }  
}  
例题1:帮派弟位

找到每个节点i 的子树大小siz[i]

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+9;
vector<int> g[N];
int siz[N];//存放包含自己在内的子树节点个数
void dfs(int x,int p){siz[x]=1;//叶子如果设为0则对父节点的size毫无影响for(const auto &y:g[x]){if(y==p) continue;dfs(y,x);siz[x]+=siz[y];}
}
struct Node{int id,siz;//rule:主要按 siz 降序(siz > u.siz) siz 相同,则按 id 升序(id < u.id)bool operator < (const Node &u)const {return siz==u.siz?id<u.id:siz>u.siz;}
};int main()
{int n,m;cin>>n>>m;for(int i=1;i<n;i++){int r,l;cin>>l>>r;//存储有向树g[r].push_back(l);}dfs(1,0);//v存储每个编号的手下人数多少vector<Node> v;//vector下标必须从0开始i=0存for(int i=0;i<n;i++) v.push_back({i,siz[i]-1});sort(v.begin(),v.end());for(int i=0;i<n;i++) if(v[i].id==m) cout<<i+1<<endl;return 0;
}
例题2: 可行路径的方案数

计算从节点 1 到节点 n 的最短路径数量

理解:

  • “当前路径” = 从城市1到 x 的已知最短路径 + 边 x→y
  • 这条路径的长度是 d[x] + 1(因为所有边权为1,即每走一步距离+1)。
  1. 如果 d[x] + 1 < d[y]
    • 发现了一条更短的路径到 y
    • 更新 d[y] = d[x] + 1,并重置 dp[y] = dp[x](因为旧路径不再有效)。
    • y 加入队列,继续探索。
  2. 如果 d[x] + 1 == d[y]
    • 找到了一条等长的最短路径y
    • 累加方案数:dp[y] += dp[x](模 p 防止溢出)。
    • 无需重复入队(因为距离未变,BFS保证先到的最短路径已处理)。
  3. 如果 d[x] + 1 > d[y]
    • 当前路径比已知最短路径长,直接跳过。
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 9;
const int p = 1e9 + 7;
vector<int> g[N];
// d[]表示从索引值城市到城市1的距离;dp[]表示从索引值城市到城市1最近的路径
int d[N], dp[N];
void bfs() {bitset<N> vis;queue<int> qu;qu.push(1);memset(d, 0x3f, sizeof d); //给每个城市最近距离初始化为无穷d[1] = 0;//1到第一个城市的距离为0dp[1] = 1; //到第一个城市方案数为1while(!qu.empty()) {//访问并取出队头 判断并标记为visitedint x = qu.front();qu.pop();if(vis[x]) continue;vis[x] = true;//找下一个城市y 判断d[y]与d[x]+1的关系for(const auto & y : g[x]) {//从城市1到城市y的距离比之前走过的远,不考虑if(d[x] + 1 > d[y]) continue;//找到另一条最短路径,累加方案数if(d[x] + 1 == d[y]) dp[y] = dp[y] + dp[x] % p;//找到一条更短的经过x y的路else 	d[y] = d[x] + 1, dp[y] = dp[x];qu.push(y);}}
}
int main() {int n, m;cin >> n >> m;//双向图for(int i = 1; i <= m; i++) {int a, b;cin >> a >> b;g[a].push_back(b);g[b].push_back(a);}bfs();cout << dp[n] << endl;return 0;
}

实例:

1 -- 2 -- 3  \   /  4

bfs过程:

  1. 从城市1出发,d[1]=0dp[1]=1

  2. 遍历1的邻居

    {2, 4}
    
    • 更新 d[2]=1dp[2]=1d[4]=1dp[4]=1
  3. 处理城市2:

    • 邻居

      {1, 3, 4}
      
      • 1已访问(d[1]=0),跳过。
      • 到3的“当前路径”长度 d[2]+1=2,更新 d[3]=2dp[3]=1
      • 到4的“当前路径”长度 d[2]+1=2,但 d[4]=1(更短),跳过。
  4. 处理城市4:

    • 邻居

      {1, 2}
      
      • 1已访问,跳过。
      • 到2的“当前路径”长度 d[4]+1=2,但 d[2]=1(更短),跳过。
  5. 处理城市3:

    • 邻居 {2},已处理。
最小生成树Kruskal

与Prim算法不同,该算法的核心思想是归并边,而Prim算法的核心思想是归并点。若边数远少于完全图,Kruskal比Prim算法更高效。

思想回顾:

在这里插入图片描述

步骤:

  1. 按照所有边权排序
  2. 从小到大遍历所有边(u,v),如果已联通就跳过,否则就选中(u,v),将其连通。(用到并查集)
模版题代码:旅行销售员

走完N个城市,每公里消耗1升油,找出所需油箱的最小容量。

#include <iostream>  
#include <vector>  
#include <algorithm>  using namespace std;  
using ll = long long;  // 使用长整型存储权值  // 边结构体:起点x、终点y、权值c  
struct Edge {  ll x, y, c;  // 重载<运算符,按权值升序排序  bool operator<(const Edge& u) const {  return c < u.c;  }  
};  // 并查集:查找根节点(带路径压缩)
//目标:确定哪些节点属于同一个连通分量,它并不关心边的方向性
int root(vector<int>& pre, int x) {  return pre[x] == x ? x : pre[x] = root(pre, pre[x]);  
}  void solve() {  int n, m;  // 节点数、边数  cin >> n >> m;  // 初始化并查集  vector<int> pre(n + 1);  for (int i = 1; i <= n; ++i) {  pre[i] = i;  // 初始时每个节点的父节点是自己  }  // 读取所有边  vector<Edge> es;  for (int i = 1; i <= m; ++i) {  ll x, y, c;  cin >> x >> y >> c;  es.push_back({x, y, c});  }  // 按边权升序排序  sort(es.begin(), es.end());  ll res = 0;  // 记录MST中的最大边权  for (const auto& edge : es) {  int x = edge.x;  int y = edge.y;  ll c = edge.c;  // 若x和y不连通,则合并它们  if (root(pre, x) != root(pre, y)) {  res = max(res, c);  // 更新最大边权  pre[root(pre, x)] = root(pre, y);  // 合并操作  }  }  cout << res << endl;  // 输出结果  
}  int main() {  int T = 0;  // 测试数据组数  cin >> T;  while (T--) {  solve();  // 处理每组数据  }  return 0;  
}
最小生成树Prim
思想回顾:

与dijkstra很像,逐步扩大树中所含顶点的数目,直到遍及连通图的所有顶点。下面描述我们假设N = ( V , E ) 是连通网,T E 是N 上最小生成树中边的集合。

在这里插入图片描述

  1. 每次找出不再mst中且d[]最小的点x,d[x]就是选中的那条边的边权。
  2. 将x加入mst,并更新其所有出点y,d[y]=min(d[y],w) //w为x到y的距离
  3. 如果d[y]变小,就加入到优先队列中作为可能的拓展点

mst使用bitset数组实现即可

代码模版题:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1E6 + 5;
ll n, m, inf = 1e9;
struct Edge {ll x, w;bool operator <(const Edge&u)const {return w > u.w; //小根堆}
};
//邻接表
vector<Edge>g[N];
//记录从起点(节点1)到各个节点的最小权重
ll d[N];
ll Prim() {//小根堆priority_queue<Edge>pq;bitset<N>vis;pq.push({1, d[1] = 0});ll res = 0;while(pq.size()) {//访问并取出元素x 判断并标记为visited//x为不在mst且权重最小的边ll x = pq.top().x;pq.pop();if(vis[x])continue;vis[x] = true;//更新mst最小权重总和res = max(res, d[x]);//遍历x所有邻接节点for(const auto & temp : g[x]) {ll y = temp.x;ll w = temp.w;//比较w和d[y] w 更小则更新d[y]if(w < d[y])pq.push({y, d[y] = w});}}return res;
}
void solve() {cin >> n >> m;//每次clear g[N]for(int i = 1; i <= n; i++)g[i].clear(), d[i] = inf;while(m--) {ll x, y, w;cin >> x >> y >> w;//输入带权值的双向边模版g[x].push_back({y, w});g[y].push_back({x, w});}cout << Prim() << endl;
}
int main() {int t;cin >> t;while(t--)solve();return 0;
}

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

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

相关文章

展讯android15源码编译之apk单编

首先找到你要单编的apk生成的路径&#xff1a; sys\out_system\target\product\ussi_arm64\system_ext\app\HelloDemo\HelloDemo.apk接着打开下面这个文件&#xff1a; sys\out_system\ussi_arm64_full-userdebug-gms.system.build.log在里面找关键字"Running command&q…

如何关闭MacOS中鼠标滚轮滚动加速

一、背景 想要关闭滚轮的 “滚动加速”&#xff0c;即希望滚动了多少就对应滚动页面固定行数&#xff0c;现在macOS是加速滚动的&#xff0c;即滚动相同的角度会根据你滚动滚轮的速度不同最终页面滚动的幅度不同。这点很烦&#xff0c;常导致很难定位。 macOS本身的设置是没有…

河北工程大学e2e平台,python

题目&#xff0c;选择题包100分&#xff01; 题目&#xff0c;选择题包100分&#xff01; 题目&#xff0c;选择题包100分&#xff01; 联系&#x1f6f0;&#xff1a;18039589633

【蓝桥杯】贪心算法

1. 区间调度 1.1. 题目 给定个区间,每个区间由开始时间start和结束时间end表示。请选择最多的互不重叠的区间,返回可以选择的区间的最大数量。 输入格式: 第一行包含一个整数n,表示区间的数量 接下来n行,每行包含两个整数,分别表示区间的开始时间和结束时间 输出格式:…

一维差分数组

2.一维差分 - 蓝桥云课 问题描述 给定一个长度为 n 的序列 a。 再给定 m 组操作&#xff0c;每次操作给定 3 个正整数 l, r, d&#xff0c;表示对 a_{l} 到 a_{r} 中的所有数增加 d。 最终输出操作结束后的序列 a。 ​​Update​​: 由于评测机过快&#xff0c;n, m 于 20…

二分答案----

二分答案 - 题目详情 - HydroOJ 问题描述 给定一个由n个数构成的序列a&#xff0c;你可以进行k次操作&#xff0c;每次操作可以选择一个数字&#xff0c;将其1&#xff0c;问k次操作以后&#xff0c;希望序列里面的最小值最大。问这个值是多少。 输入格式 第一行输入两个正…

旋转位置编码

旋转位置编码&#xff08;Rotary Position Embedding&#xff0c;RoPE&#xff09;: 一种能够将相对位置信息依赖集成到 self-attention 中并提升 transformer 架构性能的位置编码方式。 和相对位置编码相比&#xff0c;RoPE 具有更好的外推性&#xff0c;目前是大模型相对位…

.NET-EFCore基础知识

.NET EF Core&#xff08;Entity Framework Core&#xff09;是微软开发的一款开源的对象关系映射&#xff08;ORM&#xff09;框架&#xff0c;用于在.NET 应用程序中与数据库进行交互。以下是一些.NET EF Core 的基础知识&#xff1a; 1. 什么是 EF Core EF Core 是.NET 平…

利用 RNN 预测股票价格:从数据处理到可视化实战

在金融领域&#xff0c;预测股票价格走势一直是众多投资者和研究者关注的焦点。今天&#xff0c;我们将利用深度学习中的循环神经网络&#xff08;RNN&#xff09;来构建一个简单的股票价格预测模型&#xff0c;并详细介绍从数据加载、预处理、模型搭建、训练到最终结果可视化的…

LangGraph 架构详解

核心架构组件 LangGraph 的架构建立在一个灵活的基于图的系统上&#xff0c;使开发者能够定义和执行复杂的工作流。以下是主要架构组件&#xff1a; 1. 状态管理系统 LangGraph 的核心是其强大的状态管理系统&#xff0c;它允许应用程序在整个执行过程中维护一致的状态&…

Python 深度学习实战 第1章 什么是深度学习代码示例

第1章&#xff1a;什么是深度学习 内容概要 第1章介绍了深度学习的背景、发展历史及其在人工智能&#xff08;AI&#xff09;和机器学习&#xff08;ML&#xff09;中的地位。本章探讨了深度学习的定义、其与其他机器学习方法的关系&#xff0c;以及深度学习在近年来取得的成…

swift菜鸟教程1-5(语法,变量,类型,常量,字面量)

一个朴实无华的目录 今日学习内容&#xff1a;1.基本语法引入空格规范输入输出 2.变量声明变量变量输出加反斜杠括号 \\( ) 3.可选(Optionals)类型可选类型强制解析可选绑定 4.常量常量声明常量命名 5.字面量整数 and 浮点数 实例字符串 实例 今日学习内容&#xff1a; 1.基本…

GAT-GRAPH ATTENTION NETWORKS(论文笔记)

CCF等级&#xff1a;A 发布时间&#xff1a;2018年 代码位置 25年4月21日交 目录 一、简介 二、原理 1.注意力系数 2.归一化 3.特征组合与非线性变换 4.多头注意力 4.1特征拼接操作 4.2平均池化操作 三、实验性能 四、结论和未来工作 一、简介 图注意力网络&…

XML、JSON 和 Protocol Buffers (protobuf) 对比

目录 1. XML (eXtensible Markup Language) 1&#xff09;xml的特点&#xff1a; 2&#xff09;xml的适用场景&#xff1a; 2. JSON (JavaScript Object Notation) 1&#xff09;JSOM的特点&#xff1a; 2&#xff09;JSON的适用场景&#xff1a; 3. Protocol Buffers (…

如何通过简单步骤保护您的网站安全

在如今的数字化时代&#xff0c;网站安全已经成为每个网站管理者都不能忽视的重点。未授权用户入侵、数据泄露和恶意软件等威胁越来越多&#xff0c;网站安全对于保护企业、用户和客户的数据非常重要。为了帮助您提升网站的安全性&#xff0c;本文介绍了一些简单且有效的措施&a…

【后端开发】初识Spring IoC与SpringDI、图书管理系统

文章目录 图书管理系统用户登录需求分析接口定义前端页面代码服务器代码 图书列表展示需求分析接口定义前端页面部分代码服务器代码Controller层service层Dao层modle层 Spring IoC定义传统程序开发解决方案IoC优势 Spring DIIoC &DI使用主要注解 Spring IoC详解bean的存储五…

通付盾风控智能体(RiskAgent): 神烦狗(DOGE)

在数字化业务高速发展的今天&#xff0c;风控系统已成为企业抵御黑产、欺诈、保障交易安全的核心防线。然而传统风控面临人力依赖高与策略滞后性等挑战&#xff0c;数据分析师需每日从海量数据中手动提炼风险特征、设计防护规则&#xff0c;耗时费力&#xff1b;新策略从发现到…

大模型论文:Language Models are Unsupervised Multitask Learners(GPT2)

大模型论文&#xff1a;Language Models are Unsupervised Multitask Learners(GPT2) 文章地址&#xff1a;https://storage.prod.researchhub.com/uploads/papers/2020/06/01/language-models.pdf 摘要 自然语言处理任务&#xff0c;例如问答、机器翻译、阅读理解和摘要&am…

分布式ID生成方案的深度解析与Java实现

在分布式系统中&#xff0c;生成全局唯一的ID是一项核心需求&#xff0c;广泛应用于订单编号、用户信息、日志追踪等场景。分布式ID不仅需要保证全局唯一性&#xff0c;还要满足高性能、高可用性以及一定的可读性要求。本文将深入探讨分布式ID的概念、设计要点、常见生成方案&a…

记 etcd 无法在docker-compose.yml启动后无法映射数据库目录的问题

1、将etcd 单独提取 Dockerfile&#xff0c;指定配置文件和数据目录 #镜像 FROM bitnami/etcd:3.5.11 #名称 ENV name"etcd" #重启 ENV restart"always" #运行无权限 ENV ALLOW_NONE_AUTHENTICATION"yes" #端口 EXPOSE 2379 2380 #管理员权限才…