【图论】(三)图论的并查集问题

news2024/11/26 0:39:12

图论的并查集问题

  • 并查集理论基础
    • 并查集理论
    • 路径压缩
    • 代码模板
    • 模拟过程
  • 找亲戚
  • 寻找存在的路径
  • 冗余连接
  • 冗余连接II

并查集理论基础

参考学习视频: 图论——并查集(详细版)

并查集理论

并查集主要用于处理一些不相交集合的合并问题(连通性问题)

大白话就是当我们需要判断两个元素是否在同一个集合里的时候,我们就要想到用并查集。

并查集的基本操作主要有:

  • 初始化 init
  • 查询 find
  • 合并 join
  • 判断 isSame

初始化: 假如有编号为1,2,3,…, n的n个元素,我们用一个数组 fa[] 来存储每个元素的父节点。一开始,我们先将它们的父节点设为自己。

// 并查集初始化
void init(int n)
{
	for(int i = 0; i < n; i++)
		fa[i] = i;
}


查询: 通过递归函数,查找 i 的祖先

// 并查集里寻根的过程
int find(int i)
{
	if(fa[i] == i)
		return fa[i];			//递归出口,当到达了祖先位置,就返回祖先
	else
		return find(fa[i]);	// 	不断往上查找祖先

}

合并: 使得 v 的祖先(根)是 u 的祖先(根),这里可以使u的根为v的根,修改程序即可,哪种连接均可。

void join(int u, int v)
{
	int u_fa = find(u);		// 寻找u的根
	int v_fa = find(v);		// 寻找v的根
	// 如果发现根相同,则说明在一个集合,不用两个节点相连直接返回
	if(u_fa == v_fa)
		return;
	//否则v的根 = u的根
	else
		fa[v_fa] = u_fa;
}
join(1, 2);
join(3, 2);

注意:在join(int u, int v)函数里 要分别对 u 和 v 寻根之后再进行关联。

当执行 join(3, 2) 的时候,会先通过find函数寻找 3的根为3,2的根为1 (第一个join(1, 2),将2的根设置为1),所以最后是将1 指向 3。最后构成的图是这样的:


判断: 该函数则判断两个数的组祖先是否相同,相同返true,不同返回 false

// 判断 u 和 v是否找到同一个根
bool isSame(int u, int v)
{
	int u_fa = find(u);
	int v_fa = find(v);
	//根相同
	if(u_fa == v_fa)
		return true;
	else
		return false;
}

路径压缩

在实现 find 函数的过程中,我们知道,通过递归的方式,不断获取father数组下标对应的数值,最终找到这个集合的根。

搜索过程像是一个多叉树中从叶子到根节点的过程,如图:


如果这棵多叉树高度很深的话,每次find函数 去寻找根的过程就要递归很多次。

我们的目的只需要知道这些节点在同一个根下就可以,所以对这棵多叉树的构造只需要这样就可以了,如图:


我们只需要在递归的过程中,让 father[u] 接住 递归函数 find(father[u]) 的返回结果:

// 并查集里寻根的过程
int find(int i)
{
	if(fa[i] == i)
		return fa[i];			//递归出口,当到达了祖先位置,就返回祖先
	else
	{
		fa[i] = find(fa[i]);	// 	不断往上查找祖先
		return fa[i];
	}
}

代码模板

// n根据题目中节点数量而定,一般比节点数量大一点就好
int n = 100;	
vector<int> fa(n,0);

// 并查集初始化
void init(void)
{
	for(int i = 0; i < n; i++)
		fa[i] = i;
}
// 并查集里寻根的过程
int find(int i)
{
	if(fa[i] == i)
		return fa[i];			//递归出口,当到达了祖先位置,就返回祖先
	else
	{
		fa[i] = find(fa[i]);	// 	不断往上查找祖先
		return fa[i];
	}
}

void join(int u, int v)
{
	int u_fa = find(u);		// 寻找u的根
	int v_fa = find(v);		// 寻找v的根
	// 如果发现根相同,则说明在一个集合,不用两个节点相连直接返回
	if(u_fa == v_fa)
		return;
	//否则v的根 = u的根
	else
		fa[v_fa] = u_fa;
}

// 判断 u 和 v是否找到同一个根
bool isSame(int u, int v)
{
	int u_fa = find(u);
	int v_fa = find(v);
	return  u_fa == v_fa;
}

通过模板,我们可以知道,并查集主要有三个功能。

  • 寻找根节点,函数:find(int u),也就是判断这个节点的祖先节点是哪个
  • 将两个节点接入到同一个集合,函数:join(int u, int v),将两个节点连在同一个根节点上
  • 判断两个节点是否在同一个集合,函数:isSame(int u, int v),就是判断两个节点是不是同一个根节点

模拟过程

  • join(1, 8);

  • join(3, 8);

    注意:在join(int u, int v)函数里 要分别对 u 和 v 寻根之后再进行关联。

  • join(1, 7);

  • join(8, 5);

    为什么 图中 8 又直接指向了 3 了呢?因为路经压缩了

  • join(2, 9);

  • join(6, 9);

找亲戚

  现在有若干家族图谱关系,给出了一些亲戚关系,如Mrry和Tom是亲戚,Tom和Ben是亲戚等等。从这些信息中,你可以推导出Marry和Ben是亲戚。请写一个程序,对于我们的关于亲戚关系的提问,以最快速度给出答案。

输入格式:

  • 第一部分是以N,M开始。N为人数,这些人的编号为1,2,3…,N。下面有M行,每行有两个数a,b,表示a和b是亲戚.
  • 第二部分是以Q开始。以下Q行有Q个询问,每行为c,d,表示询问c和d是否为亲戚

输出格式: 对于询问c,d,输出一行: 若c,d为亲戚,则输出"YES",否则输出"NO"

输入样例:

10 7
2 4
5 7
1 3
8 9
1 2
5 6
2 3
3
3 4
7 10
8 9

输出样例:

YES
NO
YES

并查集主要有三个功能:

  • 寻找根节点,函数:find(int u),也就是判断这个节点的祖先节点是哪个
  • 两个节点接入到同一个集合,函数:join(int u, int v),将两个节点连在同一个根节点上
  • 判断两个节点是否在同一个集合,函数:isSame(int u, int v),就是判断两个节点是不是同一个根节点

思路

  • 本题就是需要将m组数据添加到集合中,建立联系
  • 熟悉差并集模板

程序实现:

#include <iostream>
#include <vector>
#include <vector>

using namespace std;

int n;		// 人数

vector<int> fa(n+1);

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

int find(int i)
{
	if(fa[i] == i)
		return fa[i];
	else
	{
		fa[i] = find(fa[i]);
		return fa[i];
	}
}

void join(int u, int v)
{
	int u_fa = find(u);
	int v_fa = find(v);
	if(u_fa == v_fa)
		return;
	fa[v_fa] = u_fa;
}

bool isSame(int u, int v)
{
	int u_fa = find(u);
	int v_fa = find(v);
	if(u_fa == v_fa)
		return true;
	else
		return false;
}

int main()
{
	int m, s, t, q;
	cin >> n >> m;
	init();
	while(m--){
		cin >> s >> t;
		join(s,t);
	}
	
	cin >> q;
	vector<bool> res(q+1);
	for(int i = 1; i <= q;i++)
	{
		cin >> s >> t;
		if(isSame(s,t))
			res[i] = true;
		else
			res[i] = false;
	}
	
	for(int i = 1; i <= q;i++)
	{
		if(res[i])
			cout << "YES" << endl;
		else
			cout << "NO" << endl;
	}
	
	return 0;
}

寻找存在的路径

寻找存在的路径

题目描述:

  • 给定一个包含 n 个节点的无向图中,节点编号从 1 到 n (含 1 和 n )。
  • 你的任务是判断是否有一条从节点 source 出发到节点 destination 的路径存在。

输入描述:

  • 第一行包含两个正整数 N 和 M,N 代表节点的个数,M 代表边的个数。
  • 后续 M 行,每行两个正整数 s 和 t,代表从节点 s 与节点 t 之间有一条边。
  • 最后一行包含两个正整数,代表起始节点 source 和目标节点 destination。

输出描述: 输出一个整数,代表是否存在从节点 source 到节点 destination 的路径。如果存在,输出 1;否则,输出 0。

输入示例:

5 4
1 2
1 3
2 4
3 4
1 4

输出示例:

1

提示信息:

思路:

  • 本题思路与上题完全一致
  • 主要就是集合问题,两个节点在不在一个集合,也可以将两个节点添加到一个集合中。

程序如下:

#include <iostream>
#include <vector>

using namespace  std;


int n;		//节点数量
vector<int> fa(n+1);

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

int find(int i)
{
	if(fa[i] == i)
		return i;
	else
	{
		fa[i] = find(fa[i]);
		return fa[i];
	}
}

void join(int u, int v)
{
	int u_fa = find(u);
	int v_fa = find(v);
	if(u_fa == v_fa)
		return;
	fa[v_fa] = u_fa;
}

bool isSame(int u, int v)
{
	int u_fa = find(u);
	int v_fa = find(v);
	if(u_fa == v_fa)
		return true;
	else
		return false;
}

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

冗余连接

卡码网题目链接(ACM模式)

题目描述

  有一个图,它是一棵树,他是拥有 n 个节点(节点编号1到n)和 n - 1 条边的连通无环无向图(其实就是一个线形图),如图1,现在在这棵树上的基础上,添加一条边(依然是n个节点,但有n条边),使这个图变成了有环图,如图2

先请你找出冗余边,删除后,使该图可以重新变成一棵树。

输入描述:

  • 第一行包含一个整数 N,表示图的节点个数和边的个数。
  • 后续 N 行,每行包含两个整数 s 和 t,表示图中 s 和 t 之间有一条边。

输出描述: 输出一条可以删除的边。如果有多个答案,请删除标准输入中最后出现的那条边。

输入示例:

3
1 2
2 3
1 3

输出示例:

1 3

提示信息:

图中的 1 2,2 3,1 3 等三条边在删除后都能使原图变为一棵合法的树。但是 1 3 由于是标准输出里最后出现的那条边,所以输出结果为 1 3

思路:

  • 并查集可以解决什么问题:两个节点是否在一个集合,也可以将两个节点添加到一个集合中。

  • 题意:无向图,返回一条可以删去的边,使得结果图是一个有着N个节点的树,如果有多个答案,则返回二维数组中最后出现的边。

  • 那么我们就可以从前向后遍历每一条边(优先让前面的边连上),边的两个节点如果不在同一个集合,就加入集合(即:同一个根节点)。

  • 如图,节点A 和节点 B 不在同一个集合,那么就可以将两个 节点连在一起。

  • 如果边的两个节点已经出现在同一个集合里,说明着边的两个节点已经连在一起了,再加入这条边一定就出现环了。如图

已经判断 节点A 和 节点B 在在同一个集合(同一个根),如果将 节点A 和 节点B 连在一起就一定会出现环。

程序实现:

#include <iostream>
#include <vector>

using namespace  std;

int n;		//节点数量

vector<int> fa(n+1);

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

int find(int i)
{
	if(fa[i] == i)
		return i;
	else
	{
		fa[i] = find(fa[i]);
		return fa[i];
	}
}

void join(int u, int v)
{
	int u_fa = find(u);
	int v_fa = find(v);
	if(u_fa == v_fa)
		return;
	fa[v_fa] = u_fa;
}

bool isSame(int u, int v)
{
	int u_fa = find(u);
	int v_fa = find(v);
	return u_fa == v_fa;
}


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);
	}
}

问1: 题意是“删除标准输入中最后出现的那条边” ,而代码分明是遇到在同一个根的两个节点立刻就返回了,怎么就求出 最后出现的那条边 了呢?

问2: 认为发现一条冗余边后,后面还可能会有一条冗余边。

题目是在 树的基础上 添加一条边,所以冗余边仅仅是一条。

到这一条可能靠前出现,可能靠后出现。

冗余连接II

卡码网题目链接(ACM模式)

题目描述:
  有一种有向树,该树只有一个根节点,所有其他节点都是该根节点的后继。该树除了根节点之外的每一个节点都有且只有一个父节点,而根节点没有父节点。有向树拥有 n 个节点和 n - 1 条边。如图1,现在有一个有向图,有向图是在有向树中的两个没有直接链接的节点中间添加一条有向边。如图2:

输入一个有向图,该图由一个有着 n 个节点(节点编号 从 1 到 n),n 条边,请返回一条可以删除的边,使得删除该条边之后该有向图可以被当作一颗有向树。

输入描述:

  • 第一行输入一个整数 N,表示有向图中节点和边的个数。
  • 后续 N 行,每行输入两个整数 s 和 t,代表这是 s 节点连接并指向 t 节点的单向边

输入一个有向图,该图由一个有着 n 个节点(节点编号 从 1 到 n),n 条边,请返回一条可以删除的边,使得删除该条边之后该有向图可以被当作一颗有向树。

输入描述

第一行输入一个整数 N,表示有向图中节点和边的个数。

后续 N 行,每行输入两个整数 s 和 t,代表这是 s 节点连接并指向 t 节点的单向边

输出描述: 输出一条可以删除的边,若有多条边可以删除,请输出标准输入中最后出现的一条边。

输入示例:

3
1 2
1 3
2 3

输出示例:

2 3

提示信息:


在删除 2 3 后有向图可以变为一棵合法的有向树,所以输出 2 3

思路

  • 本题上题冗余连接及其类似,但本题是一个有向图
  • 根据有向树的性质,只有根节点入度为0,其他节点入度都为1(因为该树除了根节点之外的每一个节点都有且只有一个父节点,而根节点没有父节点)

情况一: 如果我们找到入度为2的点,那么删一条指向该节点的边就行了(因为有向树种中的入度最大为1)


找到了节点3 的入度为2,删 1 -> 3 或者 2 -> 3 。选择删顺序靠后便可。

但入度为2 还有一种情况,情况二, 只能删特定的一条边,如图:


节点3 的入度为 2,但在删除边的时候,只能删 这条边(节点1 -> 节点3)

综上,如果发现入度为2的节点 ,我们需要判断删除哪一条边,删除后本图能成为有向树。如果是删哪个都可以,优先删顺序靠后的边。

情况三: 如果没有入度为2的点,说明 图中有环了(注意是有向环),如图

对于情况三,删掉构成环的边就可以了。

程序实现:

把每条边记录下来,并统计节点入度:

int s, t;
    vector<vector<int>> edges;
    cin >> n;
    vector<int> inDegree(n + 1, 0); // 记录节点入度
    for (int i = 0; i < n; i++) {
        cin >> s >> t;
        inDegree[t]++;
        edges.push_back({s, t});
    }

前两种入度为2的情况,一定是删除指向入度为2的节点的两条边其中的一条,如果删了一条,判断这个图是一个树,那么这条边就是答案。

同时注意要从后向前遍历,因为如果两条边删哪一条都可以成为树,就删最后那一条。

代码如下:

vector<int> vec; // 记录入度为2的边(如果有的话就两条边)
// 找入度为2的节点所对应的边,注意要倒序,因为优先删除最后出现的一条边
for(int i = n - 1; i >= 0; i--){
	if(inDegree[edges[i][1]] == 2){		//edges[i][1]: 输入时候第i条的入节点
		vec.push_back(i);
	}
}
// 有入度为2的节点
if(vec.size() > 0)
{
	// 放在vec里的边已经按照倒叙放的,所以这里就优先删vec[0]这条边
	if(isTreeAfterRemoveEdge(edges, vec[0])){
		cout << edges[vec[0]][0] << " " << edges[vec[0]][1]; 
	}
	else{
		cout << edges[vec[1]][0] << " " << edges[vec[1]][1]; 
	}
}

再来看情况三,明确没有入度为2的情况,那么一定有向环,找到构成环的边就是要删除的边。

可以定义一个函数,代码如下:

// 在有向图里找到删除的那条边,使其变成树 
void getRemoveEdge(const vector<vector<int>>& edges)

我们要解决本题要实现两个最为关键的函数:

  • isTreeAfterRemoveEdge() 判断删一个边之后是不是有向树
  • getRemoveEdge() 确定图中一定有了有向环,那么要找到需要删除的那条边,此时就用到并查集了。

isTreeAfterRemoveEdge() 判断删一个边之后是不是有向树: 将所有边的两端节点分别加入并查集,遇到要要删除的边则跳过,如果遇到即将加入并查集的边的两端节点本来就在并查集了,说明构成了环。

getRemoveEdge() 确定图中一定有了有向环,那么要找到需要删除的那条边: 将所有边的两端节点分别加入并查集,如果遇到即将加入并查集的边的两端节点本来就在并查集了,说明构成了环。

完成程序:

#include <iostream>
#include <vector>

using namespace std;

int n; 		// 节点个数
vector<int> fa(1001, 0);	

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

int find(int i)
{
	if(i == fa[i])
		return fa[i];
	else{
		fa[i] = find(fa[i]);
		return fa[i];
	}
}

void join(int u, int v)
{
	int u_fa = find(u);
	int v_fa = find(v);
	if(u_fa == v_fa)
		return;
	fa[v_fa] = u_fa;
}

bool isSame(int u, int v)
{
	int u_fa = find(u);
	int v_fa = find(v);
	if(u_fa == v_fa)
		return true;
	else
		return false;
}


// 删一条边之后判断是不是树
bool isTreeAfterRemoveEdge(vector<vector<int>> &edges, int deleteEdge)
{
	init(); // 初始化并查集
	for(int i = 0; i < n; i++)
	{
		if(i == deleteEdge)
			continue;
		// 构成有向环了,一定不是树
		if(isSame(edges[i][0], edges[i][1]))
			return false;
		join(edges[i][0], edges[i][1]);
	}
	return true;
}

// 在有向图里找到删除的那条边,使其变成树
void getRemoveEdge(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];
			return;
		}
		else
			join(edges[i][0], edges[i][1]);
	}
}

int main()
{
	int s, t;
	cin >> n;
	vector<vector<int>> edges;		// 记录边
	vector<int> inDegree(n + 1, 0); // 记录节点入度
	for(int i = 0; i < n; i++)
	{
		cin >> s >> t;
		inDegree[t]++;				// 入节点数++
		edges.push_back({s,t});		// 边如容器
		
	}
	
	vector<int> vec; // 记录入度为2的边(如果有的话就两条边)
	// 找入度为2的节点所对应的边,注意要倒序,因为优先删除最后出现的一条边
	for(int i = n - 1; i >= 0; i--){
		if(inDegree[edges[i][1]] == 2){		//edges[i][1]: 输入时候第i条的入节点
			vec.push_back(i);
		}
	}
	// 有入度为2的节点 情况一、二
	if(vec.size() > 0)
	{
		// 放在vec里的边已经按照倒叙放的,所以这里就优先删vec[0]这条边
		if(isTreeAfterRemoveEdge(edges, vec[0])){
			cout << edges[vec[0]][0] << " " << edges[vec[0]][1]; 
		}
		else{
			cout << edges[vec[1]][0] << " " << edges[vec[1]][1]; 
		}
		return 0;
	}
	
	// 处理情况三
	// 明确没有入度为2的情况,那么一定有有向环,找到构成环的边返回就可以了
	getRemoveEdge(edges);
	return 0;
}

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

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

相关文章

汽车网络安全 -- 后量子密码时代还远吗?

目录 1.量子计算对密码学的威胁 1.1 传统密码学速览 1.2 量子计算对密码学的威胁 2.后量子密码学 2.1 量子计算原理 2.2 后量子密码学 3.未来汽车网络安全面临的威胁 3.1 量子计算对汽车的威胁 3.2 TC4xx对于PQC算法的支持 国庆抽空回顾了下Hitex组织的《Designing wi…

西门子S7-1200选型指南之概述

S7-1200 控制器概述 S7-1200 虽然只是中小型控制器&#xff0c;但是功能很全面。它具有较高性能&#xff0c;并且具有很强的扩展能力&#xff0c;通信能力多种多样&#xff0c;本体即具有各种常见工艺功能&#xff0c;此外也具备西门子常见的诊断功能&#xff0c;下面将分几部…

vue3 + vite + cesium项目

GitHub - tingyuxuan2302/cesium-vue3-vite: 项目基于 vue3 vite cesium&#xff0c;已实现常见三维动画场&#xff0c;欢迎有兴趣的同学加入共建&#xff0c;官网服务器相对拉胯&#xff0c;请耐心等候...https://github.com/tingyuxuan2302/cesium-vue3-vite/tree/github

计算机网络:数据链路层 —— 数据链路层的三个重要问题

文章目录 数据链路层的重要问题封装成帧封装过程帧的数据载荷 透明传输实现透明传输 差错检测传输差错误码&#xff08;比特差错&#xff09;分组丢失分组失序分组重复 奇偶校验循环冗余校验生成多项式方法流程 纠错码 数据链路层的重要问题 封装成帧 在计算机网络中&#xf…

基于Java+SpringBoot+Uniapp的博客系统设计与实现

项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而不是配置文件。Spring Boot 通过自动化配置和约…

Jenkins整合Docker实现CICD自动化部署(若依项目)

前期准备 提前准备好jenkins环境 并且jenkins能使用docker命令&#xff0c;并且已经配置好了jdk、node、maven环境&#xff0c;我之前写了安装jenkins的博客&#xff0c;里面讲得比较详细&#xff0c;推荐用我这种方式安装 docker安装jenkins&#xff0c;并配置jdk、node和m…

【分布式架构】分布式事务理论与实践

一、分布式事务理论 1. ACID理论 场景&#xff1a;单机架构中保证事务的理论 2. CAP理论 场景&#xff1a;分布式架构中保证事务的理论 概念 一致性&#xff1a;数据在不同的节点每一时刻都是一致的可用性&#xff1a;一部分的节点出现异常&#xff0c;但是系统仍然可用分…

【3dgs】3DGS与NeRF对比

以下是 3DGS&#xff08;3D Geometry Sensing&#xff09;与 NeRF&#xff08;Neural Radiance Fields&#xff09;对比表格&#xff1a; 更加详细的资料&#xff0c;轻参考&#xff1a; NERF/3DGS 对比维度3DGS (3D Geometry Sensing)NeRF (Neural Radiance Fields)基本原理…

【Linux进程信号】Linux信号产生机制详解:掌握系统通信的关键

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;Linux “ 登神长阶 ” &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀Linux进程信号 &#x1f4d2;1. 信号入门&#x1f4dc;2. 信号捕捉初识&#x1f4da;3. 信号…

Windows应急响蓝安服面试

Windows应急响应 蓝队溯源流程 学习Windows应急首先要站在攻击者的角度去学习一些权限维持和权限提升的方法.,文章中的方法其实和内网攻防笔记有类似l红队教你怎么利用 蓝队教你怎么排查 攻防一体,应急响应排查这些项目就可以 端口/服务/进程/后门文件都是为了权限维持,得到s…

linux安装hadoop

目录 jdk安装配置 hadoop安装 hadoop配置 配置ssh免密登录 启动hadoop 实现文件上传下载 eclipse安装配置 jdk安装配置 1、删除centos自带的jdk yum list installed | grep java yum remove *openjdk* 2、下载jdk安装包 wget --no-check-certificate https://repo.h…

InternVid:用于多模态视频理解与生成的大规模视频-文本数据集 | ICLR Spotlight

InternVid 是一个开源的大规模视频-文本数据集&#xff0c;旨在促进视频理解和生成任务的发展&#xff0c;由上海人工智能实验室与南京大学、中国科学院等单位联合发布&#xff0c;相关的工作已经被ICLR2024接收。它包含超过 700 万个视频&#xff0c;总时长近 76 万小时&#…

位操作位操作位操作

呵呵哈哈哈哈哈哈哈哈哈和哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈

MySQL—视图

前言&#xff1a; 视图是一个虚拟的表&#xff0c;是基于一个或多个基本表或其他视图的查询结果集。视图本身不占据物理储存空间&#xff0c;仅仅只是一个查询的逻辑表示&#xff0c;物理上依赖于数据表的数据。 视图具有简单&#xff0c;安全&#xff0c;逻辑数据独立&#…

CST软件优化超表面--- 偏振片- 线圆极化转换,天线阵任务,远场算轴比AR

本期我们继续看线极化转圆极化。本案例是个三层结构&#xff0c;比单层的偏振片有更宽的频率和更少的反射。我们将利用CST的天线阵列任务中的单元任务&#xff0c;加上优化器优化&#xff0c;使偏振片在多个入射角、多个频率&#xff0c;S11反射都够小&#xff0c;AR都够圆。 …

Spark-RDD的宽窄依赖以及Shuffle优化

目录 RDD宽窄依赖的区别 DAG有向无环图 窄依赖 宽依赖 shuffle过程 Shuffle介绍 Spark优化-避免shuffle RDD宽窄依赖的区别 窄依赖 每个父RDD的一个Partition最多被子RDD的一个Partition所使用 mapflatMapfilter宽依赖 一个父RDD的Partition会被多个子RDD的Partition所使…

LCD补充

LCD补充 目录 LCD补充 tip:随着我们学的越来越多&#xff0c;代码长度越来越长&#xff0c;编译越来越慢&#xff0c;有没有超过内存是我们比较关心的一件事&#xff0c;通过以下方法可以实时看到写的代码的大小 回顾LCD LCD补充功能 -- 1、有关在LCD上显示动图&#xff…

Python库matplotlib之九

Python库matplotlib之九 动画ArtistAnimation构造器成员函数应用例子 动画 Matplotlib基于其绘图功能&#xff0c;还提供了一个使用动画模块&#xff0c;生成动画的接口。动画是一系列帧&#xff0c;其中每个帧对应于图形上的一个图。 Matplotlib使用两个类来实现动画&#x…

ordinaryroad-barrage-fly wsl部署记录

系统&#xff1a;win11 wsl版本&#xff1a;wsl2 Linux&#xff1a;Ubuntu 22.04.4 LTS 文档&#xff1a;https://barragefly.ordinaryroad.tech/deploy/#_2-1-docker-compose docker相关的内容自己事先安装好 git clone https://github.com/OrdinaryRoad-Project/ordinaryr…

TensorBoard

1、概念 TensorBoard可以看作是一个“训练监控仪表盘”&#xff0c;可以 将训练过程中的数据可视化&#xff0c;让你通过图表直观地看到模型的表现&#xff0c; 识别问题&#xff0c;并进行调试和优化。 TensorFlow是用来训练模型的深度学习框架&#xff0c;在使用tensorflo…