一本通 3.4.4 并查集

news2024/11/24 9:19:09

1346:【例4-7】亲戚(relation)

【题目描述】

或许你并不知道,你的某个朋友是你的亲戚。他可能是你的曾祖父的外公的女婿的外甥女的表姐的孙子。如果能得到完整的家谱,判断两个人是否是亲戚应该是可行的,但如果两个人的最近公共祖先与他们相隔好几代,使得家谱十分庞大,那么检验亲戚关系实非人力所能及。在这种情况下,最好的帮手就是计算机。为了将问题简化,你将得到一些亲戚关系的信息,如Marry和Tom是亲戚,Tom和Ben是亲戚,等等。从这些信息中,你可以推出Marry和Ben是亲戚。请写一个程序,对于我们的关于亲戚关系的提问,以最快的速度给出答案。

【题目分析】

一般并查集的执行过程,查find函数带路径压缩,并union函数将左侧归顺右侧,查询功能如果两个点的祖先不是同一个输出No,否则输出Yes
特别的:输入输出数据较大,使用scanf与printf函数

【代码实现】

#include<bits/stdc++.h>
using namespace std;

int fa[20005], x, y;

int get(int a) {
	return fa[a] == a ? a : fa[a] = get(fa[a]);
}
void join(int a, int b) {
	int fa_a = get(a);
	int fa_b = get(b);
	if (fa_a != fa_b) fa[fa_a] = fa_b;
}
int main() {
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		fa[i] = i;
	}
	for (int i = 1; i <= m; i++) {
		scanf("%d%d", &x, &y);
		join(x, y);
	}
	cin >> m;
	for (int i = 1; i <= m; i++) {
		scanf("%d%d", &x, &y);
		if (get(x) == get(y)) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}

1347:【例4-8】格子游戏

【题目描述】

Alice和Bob玩了一个古老的游戏:首先画一个n × n的点阵(下图n = 3)

接着,他们两个轮流在相邻的点之间画上红边和蓝边:

直到围成一个封闭的圈(面积不必为1)为止,“封圈”的那个人就是赢家。因为棋盘实在是太大了(n ≤ 200),他们的游戏实在是太长了!他们甚至在游戏中都不知道谁赢得了游戏。于是请你写一个程序,帮助他们计算他们是否结束了游戏? 

【题目分析】

并查集找环:将一条边进行合并时,首先判断边的两个端点是否属于同一个集合,如果是,已经存在环,否则不存在环,合并两点的祖先。

特别的:本题中的对象不是单个数值是点数据,需要定义点的结构体进行存储,初始化将二维数组的编号与存储的点对应相等,判断时需要同时满足x、y都相等才说明祖先相同(也可以使用pair存储)。

【代码实现】

#include <bits/stdc++.h>
using namespace std;

int n, m;
struct Point {
	int x;
	int y;
} father_p[205][205], p1, p2;

Point find(Point p) {
	int x = p.x;
	int y = p.y;
	if (father_p[x][y].x == x && father_p[x][y].y == y) return p;
	else {
		return father_p[x][y] = find(father_p[x][y]);
	}
}
void unionn(Point p1, Point p2) {
	Point fa_p1 = find(p1);
	Point fa_p2 = find(p2);
	if (fa_p1.x != fa_p2.x || fa_p1.y != fa_p2.y) {
		int x = p2.x;
		int y = p2.y;
		father_p[x][y] = fa_p1;
	}
}
int main() {
	//input data
	//clock_t s = clock();
	cin >> n >> m;
	//init
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) {
			father_p[i][j].x = i;
			father_p[i][j].y = j;
		}

	for (int i = 1; i <= m; i++) {
		int x, y;
		char c;
		cin >> x >> y >> c;
		if (c == 'D') {
			Point pp;
			pp.x = x;
			pp.y = y;
			p1 = find(pp);
			pp.x = x + 1;
			pp.y = y;
			p2 = find(pp);
		}
		if (c == 'R') {
			Point pp;
			pp.x = x;
			pp.y = y;
			p1 = find(pp);
			pp.x = x;
			pp.y = y + 1;
			p2 = find(pp);
		}

		if (p1.x == p2.x && p1.y == p2.y) {
			cout << i << endl;
			return 0;
		} else {
			unionn(p1, p2);
		}
	}
	cout << "draw" << endl;

	//output time
	//cout <<endl<< clock() - s<<endl;
	return 0;
}

1385:团伙(group)

【题目描述】

在某城市里住着n个人,任何两个认识的人不是朋友就是敌人,而且满足:

1、我朋友的朋友是我的朋友;

2、我敌人的敌人是我的朋友;

所有是朋友的人组成一个团伙。告诉你关于这n个人的m条信息,即某两个人是朋友,或者某两个人是敌人,请你编写一个程序,计算出这个城市最多可能有多少个团伙?

【题目分析】

扩展域并查集:将点x进行分解,x表示x本身,x+n表示x的敌人,y表示y本身,y+n表示y的敌人,如果x与y时朋友需要将x和y合并,x+n与y+n合并,如果x与y是敌人,需要将x+n与y合并,x与y+n合并。

特别的:定义祖先数组时需要扩展2倍,判断团伙数量只需要查找fa[i]==i的数量

【代码实现】

#include<bits/stdc++.h>
#define N 100001
using namespace std;
int f[N], d[N], n, m;
int find(int x) {
	return f[x] == x ? x : f[x] = find(f[x]);
}
void fun(int x, int y) {
	x = find(x);
	y = find(y);
	if (x != y)
		f[y] = x;
}
int main() {
	cin >> n >> m;
	for (int i = 1; i <= n * 2; i++) {
		f[i] = i;
	}
	for (int i = 1; i <= m; i++) {
		int z, x, y;
		cin >> z >> x >> y;
		if (z == 0)fun(x, y);
		else if (z == 1)fun(x + n, y), fun(x, y + n);
	}
	int sum = 0;
	for (int i = 1; i <= n; i++) {
		int z = find(i);
		if (!d[z]) {
			d[z] = 1;
			sum++;
		}
	}
	cout << sum;
	return 0;
}

1386:打击犯罪(black)

【题目描述】

某个地区有n(n<=1000)个犯罪团伙,当地警方按照他们的危险程度由高到低给他们编号为1-n,他们有些团伙之间有直接联系,但是任意两个团伙都可以通过直接或间接的方式联系,这样这里就形成了一个庞大的犯罪集团,犯罪集团的危险程度由集团内的犯罪团伙数量唯一确定,而与单个犯罪团伙的危险程度无关(该犯罪集团的危险程度为n)。现在当地警方希望花尽量少的时间(即打击掉尽量少的团伙),使得庞大的犯罪集团分离成若干个较小的集团,并且他们中最大的一个的危险程度不超过n/2。为达到最好的效果,他们将按顺序打击掉编号1到k的犯罪团伙,请编程求出k的最小值。

【题目分析】

带权并查集
正向思维:使用邻接矩阵存储连边关系,从1~n枚举去掉1-k的点(k的范围从1-n),查询最大集合点数是否不超过n/2,则为答案,每次枚举都要重置并查集,时间复杂度:O(n^3) 
逆向思考:n ~ 1枚举,每次把K加入图中,也就是删除1 ~ K-1,剩余k ~ n,若最大集合点不超过N/2这个方案可行还可能更小,一旦不满足就是不能再加K,即K 要删掉,就输出答案。时间复杂度:O(n^3)

【代码实现】

#include <bits/stdc++.h>
using namespace std;

int n, m;
int father[1005];
int group_num[1005];
vector<int > group[1005];

int find(int x) {
	if (father[x] != x)
		father[x] = find(father[x]); //路径压缩
	return  father[x];
}
void unionn(int x, int y) {
	int fa_x = find(x);
	int fa_y = find(y);
	if (fa_x != fa_y) {
		father[fa_y] = fa_x;
		int nfx = group_num[fa_x];
		int nfy = group_num[fa_y];
		group_num[fa_x] += nfy;
		group_num[fa_y] += nfx;
	}

}
int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		father[i] = i;
		group_num[i] = 1;
	}
	for (int i = 1; i <= n; i++) {
		int p, x;
		cin >> p;
		group[i].push_back(p);
		for (int j = 1; j <= p; j++) {
			cin >> x;
			group[i].push_back(x);
		}
	}

	for (int i = n; i >= 1; i--) {
		for (int j = 1; j < (int)group[i].size(); j++) {
			if (group[i][j] >= i) {
				unionn(group[i][j], i);
				for (int k = 1; k <= n; k++) {
					if (group_num[k] > (n >> 1)) {
						cout << i;
						return 0;
					}
				}
			}
		}
	}

	return 0;
}

1387:搭配购买(buy)

【题目描述】

Joe觉得云朵很美,决定去山上的商店买一些云朵。商店里有n朵云,云朵被编号为1,2,…,n,并且每朵云都有一个价值。但是商店老板跟他说,一些云朵要搭配来买才好,所以买一朵云则与这朵云有搭配的云都要买。

但是Joe的钱有限,所以他希望买的价值越多越好。

【题目分析】

带权并查集:使用并查集算出每个云朵集合的最大价值和花费,使用0-1背包进行问题求解

定义fa[]数组存储云朵的祖先,value[]数组存储云朵所在集合的价值,money[]数组存储云朵所在集合的花费.
使用并查集合并云朵集合,得到每个集合的价值和花费,例如将a合并到b中,yuan[fa[b]].value+=yuan[fa[a]].value    yuan[fa[b]].money +=yuan[fa[a]].money
检查所有并查集获得云朵集合的价值value[]和费用money[],个数为cnt,总钱数为w,使用0-1背包求解最大价值dp[w]
for(i=1;i<=cnt;i++)
     for(j=w;j>=dc[i];j--)
          dp[j]=max(dp[j],dp[j-money[i]]+value[i])

【代码实现】

#include <bits/stdc++.h>
using namespace std;

int n, m, w;
const int maxn = 10005;
int money[maxn], value[maxn], dp[maxn];
struct Yun {
	int father;
	int money;
	int value;
} yun[maxn];

int find(int y) {
	if (yun[y].father != y) {
		yun[y].father = find(yun[y].father);
	}
	return yun[y].father;
}

bool cmp(const Yun& a, const Yun& b) {
	return a.value > b.value;
}
int main() {
	//input data
	//clock_t s = clock();
	cin >> n >> m >> w;

	for (int i = 1; i <= n; i++) {
		yun[i].father = i;
		cin >> yun[i].money;
		cin >> yun[i].value;
	}

	for (int i = 1; i <= m; i++) {
		int x, y;
		cin >> x >> y;
		int fa_x = find(x);
		int fa_y = find(y);
		if (fa_x != fa_y) {
			yun[fa_y].father = fa_x;
			yun[fa_y].money += yun[fa_x].money;
			yun[fa_x].money = yun[fa_y].money;
			yun[fa_y].value += yun[fa_x].value;
			yun[fa_x].value = yun[fa_y].value;
		}
	}
	int cnt = 0;
	for (int i = 1; i <= n; i++) {
		if (yun[i].father == i) {
			money[++cnt] = yun[i].money;
			value[cnt]  = yun[i].value;
		}
	}



	for (int i = 1; i <= cnt; i++) {
		for (int j = w; j >= money[i]; j--) {
			dp[j] = max(dp[j], dp[j - money[i]] + value[i]);
		}
	}
//	sort(yun+1, yun + n+1, cmp);
	cout << dp[w];
	return 0;
}

1388:家谱(gen)

【题目描述】

现代的人对于本家族血统越来越感兴趣,现在给出充足的父子关系,请你编写程序找到某个人的最早的祖先。

【题目分析】

问题本质:给定合并顺序的并查集

定义关联容器map数组 fa[]存储字符串,获取每一行字符判断第一个字符如果为#,分割字符串fat,初始化fa[fat]=fat,如果为+,分割字符串son,指定son的父亲节点fa[son]=find(fat),如果为?,分割字符串son,输出查询结果fa[son],如果为$,结束运行

【代码实现】

#include <bits/stdc++.h>
using namespace std;

map<string, string > father;

string find(string s) {
	if (father[s] != s)
		father[s] = find(father[s]);
	return father[s];
}

int main() {
	//input data
	//clock_t s = clock();
	string in;
	string fa;
	string son;
	string que;
	while (cin >> in, in != "$") {
		if (in[0] == '#') {
			fa = in.substr(1);
			if (father[fa] == "") father[fa] = fa;
		}
		if (in[0] == '+') {
			son = in.substr(1);
			father[son] = find(fa);
		}
		if (in[0] == '?') {
			que = in.substr(1);
			cout << que << " " << find(que) << endl;
		}
	}
	//output time
	//cout <<endl<< clock() - s<<endl;
	return 0;
}

1389:亲戚

【题目描述】

若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的某个人所在家族的人数。

规定:x和y是亲戚,y和z是亲戚,那么x和z也是亲戚。如果x,y是亲戚,那么x的亲戚都是y的亲戚,y的亲戚也都是x的亲戚。

【题目分析】

带权并查集:集合元素包含家族人数,询问某个人先找到该人的祖先,并输出祖先的人数

定义并查集关联数组fa[],集合个数数组sum[],获取关系字符c,如果c=='M',将a合并给b,sum[fa_b]+=sum[fa_a],如果c=='Q',输出sum[fa_q]

【代码实现】

#include <bits/stdc++.h>
using namespace std;

int father[100005];
int sum[100005];
int n, m;
int find(int x) {
	if (father[x] != x)
		father[x] = find(father[x]);
	return father[x];
}

int main() {
	//input data
	//clock_t s = clock();
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		father[i] = i;
		sum[i] = 1;
	}
	
	for (int i = 1; i <= m; i++) {
		char c;
		int a, b;
		scanf("%c",&c);scanf("%c",&c);
		if (c == 'M') {
			scanf("%d%d", &a, &b);
			int fa_a = find(a); 
			int fa_b = find(b);
			if (fa_a != fa_b) {
				father[fa_b] = fa_a;
				sum[fa_a] += sum[fa_b];
			}
		} 
		if(c=='Q') {
			scanf("%d", &a);
			printf("%d\n", sum[find(a)]);
		}
	}

	//output time
	//cout <<endl<< clock() - s<<endl;
	return 0;
}

1390:食物链【NOI2001】

【题目描述】

动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形。A吃B, B吃C,C吃A。

现有N个动物,以1-N编号。每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种。

有人用两种说法对这N个动物所构成的食物链关系进行描述:

第一种说法是"1 X Y",表示X和Y是同类。

第二种说法是"2 X Y",表示X吃Y。

此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。

1)当前的话与前面的某些真的话冲突,就是假话;

2)当前的话中X或Y比N大,就是假话;

3)当前的话表示X吃X,就是假话。

你的任务是根据给定的N(1≤ N ≤50,000)和K句话(0≤K≤100,000),输出假话的总数。

【题目分析】

扩展域并查集:将x进行关系分解,x表示自身,x+n表示x的食物,x+2*n表示x的敌人,同样y表示自身,y+n表示x的食物,y+2*n表示x的敌人

x与y是同类,如果x能够吃掉y或者y能够吃掉x,该命题都为假,find(x+n)==find(y)||find(y+n)==find(x)
否则合并x与y,合并x+n与y+n,合并x+2*n与y+2*n
x可以吃掉y,如果x与y是同类或者y可以吃掉x,该命题都为假,find(x)==find(y)||find(y+n)==find(x)
否则合并x+n与y,合并x与y+2*n,合并x+2*n与y+n

统计假命题的个数进行答案输出

【代码实现】

#include<bits/stdc++.h>
using namespace std;


int fa[150005], x, y, p;

int get(int a) {
	return fa[a] == a ? a : fa[a] = get(fa[a]);
}
void join(int a, int b) {
	int fa_a = get(a);
	int fa_b = get(b);
	if (fa_a != fa_b) fa[fa_a] = fa_b;
}

int main() {

	int m, n;
	cin >> n >> m;
	for (int i = 1; i <= 3 * n; i++) {
		fa[i] = i;
	}
	int ans = 0;
	for (int i = 1; i <= m; i++) {
		cin >> p >> x >> y;
		if (x > n || y > n) ans++;
		else if (p == 2 && x == y) ans++;
		else {
			if (p == 1) {
				if (get(x + n) == get(y) || get(x) == get(y + n)) ans++;
				else join(x, y), join(x + n, y + n), join(x + 2 * n, y + 2 * n);

			} else {
				if (get(x) == get(y) || get(x) == get(y + n)) ans++;
				else join(x + n, y), join(x, y + 2 * n), join(x + 2 * n, y + n);
			}
		}
	}
	cout << ans << endl;
	return 0;
}

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

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

相关文章

企业想注销境外投资备案应该怎么做?

我们今天就来说一下关于境外投资备案的注销&#xff0c;有办理的需求&#xff0c;当然就有注销的需求。如果您当初想去海外投资并购一家公司&#xff0c;因此办理了境外投资备案&#xff0c;但是由于种种原因可能没有办法投资下去了&#xff0c;那么这个时候我们就需要做境外投…

【Linux网络服务】SSH远程访问及控制

一、openssh服务器 1.1ssh协议 SSH&#xff08;Secure Shell&#xff09;是一种安全通道协议&#xff0c;主要用来实现字符界面的远程登录、远程 复制等功能&#xff1b; SSH 协议对通信双方的数据传输进行了加密处理&#xff0c;其中包括用户登录时输入的用户口令&#xff1…

测试月入30K,Soeasy?测试这一行涨薪机制被我摸透了...

1.软件测试如何实现涨薪 首先涨薪并不是从8000涨到9000这种涨薪&#xff0c;而是从8000涨到15K加到25K的涨薪。基本上三年之内就可以实现。 如果我们只是普通的有应届毕业生或者是普通本科那我们就只能从小公司开始慢慢往上走。 有些同学想去做测试&#xff0c;是希望能够日…

nodejs+vue 智能餐厅菜品厨位分配管理系统

系统功能主要介绍以下几点&#xff1a; 本智能餐厅管理系统主要包括三大功能模块&#xff0c;即用户功能模块和管理员功能模块、厨房功能模块。 &#xff08;1&#xff09;管理员模块&#xff1a;系统中的核心用户是管理员&#xff0c;管理员登录后&#xff0c;通过管理员功能来…

BPF之前端工具BCC与bpftrace

BPF前端工具BCC与bpftrace 一、概述 BCC和bpftrace到底是什么&#xff0c;与BPF是什么关系呢&#xff1f; 经过上一篇的介绍&#xff0c;BPF是内核中的执行引擎&#xff0c;BCC和bpftrace则是两个前端工具&#xff0c;比如用户可以直接使用的命令行工具。 BCC与bpftrace又有…

Stable Diffusion Lora模型训练详细教程

1. 介绍 通过Lora小模型可以控制很多特定场景的内容生成。 但是那些模型是别人训练好的&#xff0c;你肯定很好奇&#xff0c;我也想训练一个自己的专属模型&#xff08;也叫炼丹&#xff5e;_&#xff5e;&#xff09;。 甚至可以训练一个专属家庭版的模型&#xff08;fami…

JDK JRE JVM之间的关系

文章目录 1.从定义的角度解释JDK、JRE、JVM2、详细介绍JDK3、详细介绍JRE4、详细介绍JVM1、JVM内部区域划分 5、如何运行一个java程序&#xff1f; 本篇文章仅仅是个人片面观点&#xff0c;可能有错误或者表述不清的地方 1.从定义的角度解释JDK、JRE、JVM JDK&#xff1a;Java…

ArcGIS面要素最小外接矩形、外接圆的绘制方法

本文介绍在ArcMap软件中&#xff0c;基于一个面图层&#xff0c;绘制其中面要素的最小外接矩形、最小外接圆等的方法。 首先&#xff0c;我们来看一下本文需要实现的需求。现有一个面要素图层&#xff0c;其中包含多个面要素&#xff0c;如下图所示。我们希望绘制这个面要素图层…

【Redis】Redis十大数据类型—列表List

介绍 List列表是简单的字符串列表&#xff0c;按照插入顺序排序&#xff0c;可以从头部或尾部向List列表添加元素。 列表的最大长度是2^32-1&#xff0c;也就是每个列表支持超过40亿个元素。 实现 底层数据结构是由双向链表或压缩列表实现。 如果列表的元素个数小于 512 个…

Python获取某乎问答区计算机专业学生应聘保洁这一内容,看看为啥会有此事发生

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 不知道现在还有多少人玩知某乎&#xff0c; 今天刷话题的时候看到这么一个问答&#xff0c; 这么有趣的话题&#xff0c;咱们就对其问答内容进行采集一下&#xff1f;&#xff1f; 效果展示 可以看到&#xff0c;数据…

Linux 远程访问控制 SSH SCP SFTP TCP-Wrappers

SSH&#xff08;secure shell&#xff09;协议 一种安全通道协议&#xff0c;主要用来实现字符界面的远程登录、远程复制等功能。 协议对通信双方的数据传输进行了加密处理&#xff0c;其中包括用户登录时输入的用户口令 SSH客户端<-----------------网络------------------…

android 布局优化

1.绘制和布局加载原理 本文仅供个人学习记录&#xff0c;详细介绍可查看下面链接 Android布局优化&#xff0c;多套方案全面解析 布局优化的原因&#xff1a;布局嵌套过深&#xff0c;或者其他原因导致布局渲染性能不佳&#xff0c;可能会导致应用卡顿。 android绘制原理&am…

5.3 牛顿-科茨公式

学习目标&#xff1a; 理解微积分基础知识&#xff0c;例如导数和微分的概念。学习牛顿-科茨公式的推导过程。这个公式实际上是使用泰勒公式对被积函数进行展开&#xff0c;并使用微积分的基本原理进行简化得到的。学习如何使用牛顿-科茨公式进行数值积分。这通常涉及到将被积…

Ajax超详解(新手入门指南)

文章目录 1. AJAX简介2. 前后端交互3. XHR3.1 XMLHttpRequest对象3.2 获取模拟的后端数据3.3 获取网络数据3.4 使用json-server模拟服务器3.4.1 安装node.js3.4.2 安装并使用json-server 3.5 常见的请求方式3.5.1 GET请求3.5.2 POST请求3.5.3 PUT请求3.5.4 PATCH请求3.5.5 DELE…

【图像分割】Segment Anything(Meta AI)论文解读

文章目录 摘要一、引言二、segment anything任务1.任务2.预训练3.zero shot transfer4.相关任务5.讨论 三*、Segment Anything 模型四、Segment Anything 数据引擎五、Segment Anything 数据集六、Segment Anything RAI分析七、Zero-Shot Transfer 实验1.zero shot 单点有效掩模…

springboot本地local配置覆盖远程Apollo配置(含Apollo配置加载顺序说明)

手打不易&#xff0c;如果转摘&#xff0c;请注明出处&#xff01; 注明原文&#xff1a;https://zhangxiaofan.blog.csdn.net/article/details/130302692 目录 前言 Apollo配置加载顺序 步骤 第一步&#xff1a;Apollo创建properties 第二步&#xff1a;添加namespaces&…

js的dom事件流、事件委托和阻止绑定事件触发

主要讲解事件绑定和事件委托&#xff0c;onclick事件和addEventListener的区别 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge">&l…

IT项目管理计算题【太原理工大学】

计算题好像也没多少考点&#xff0c;主要就是记公式吧&#xff0c;其他的不想看了&#xff0c;直接考啥看啥&#xff0c;就看两个&#xff1a; ① 根据进度网络图写出时间参数表&#xff0c;ES、EF、LS、LF、TF 以及 FF&#xff0c;关键路径&#xff0c;总工期&#xff1b;② 挣…

volatile 保证内存变量可见性的实现原理解析

目录 volatile 的定义 可见性问题 JMM&#xff08;JavaMemoryModel&#xff09; 保证可见性 现代计算机的内存模型 MESI&#xff08;缓存一致性协议&#xff09; 嗅探 总线风暴 volatile 的两条实现原则 volatile 的定义 Java代码在编译后会编程 Java …

GD(兆易创新)系列FLASH进行FPGA和ZYNQ配置固化相操作

写在前面 本文主要针对使用GD&#xff08;兆易创新&#xff09;系列的FLASH做启动配置片时&#xff0c;遇到的相关问题进行简单整理复盘&#xff0c;避免后人踩坑。 本人操作固化芯片型号为&#xff1a;ZYNQ7045、690T&#xff08;复旦微替代型号V7 690T&#xff09;。 7系列…