图的简单处理(C/C++)

news2024/12/28 21:04:30

目录

1  存图方法

1.1  邻接矩阵

1.2  邻接表

1.3  链式前向星

2  树形DP

2.1  简介

2.2  例题1:公司聚会

2.3  例题2:士兵部署

2.4  例题3:强力党逗志芃

2.5  例题4:作物杂交(不确定树的结构)

3  并查集

3.1  简介

3.2  模板

3.3  例题

题目描述

4  最小生成树


1  存图方法

1.1  邻接矩阵

假设有这样一张图:

拿一张表存储信息:

 这样可以精确存储每一条路的信息,但发现空间复杂度太大,于是想其他办法优化

1.2  邻接表

假设有这样一张图:

拿这样的图存储信息: 

 其中矩形的第一个框内的信息代表到达的某点的序号,第二个框内的信息代表到达某点消耗的时间,第三个框内的信息代表下一个框的位置

1.3  链式前向星

其实链式前向星就是邻接表

我们做如下变换:

命令头部位置H1,H2,H3,H4,H5得:

 这就是头指针的位置

初始化定义结构体得:

struct E//定义结构体 
{
	int to,w,next;
}Edge[maxm];
int tot,Head[maxm];

遍历有:

for(int i=Head[u];~i;i=Edge[i].next)//遍历 
{
	int v=Edge[i].to;
	int w=Edge[i].w;
	//...
}

如果此时想插入一个点,注意插入一定要从头插,即让新插入的这个点成为第一个点:

void AddEdge(int u,int v,int w)//加点 
{
	Edge[tot].to=v;
	Edge[tot].w=w;
	Edge[tot].next=Head[u];
	Head[u]=tot++;
}

2  树形DP

2.1  简介

假设有这样一棵树:

 这是一棵无根树

我们随机找一个点作为根结点,可以变成有根树:

我们通过例题讲解具体思路。 

2.2  例题1:公司聚会

 假设u为根结点,定义二维数组dp[][]表示状态

dp[u][0]表示u不参加聚会的情况下以u为根的子树的欢乐值的最大值

dp[u][1]表示u参加聚会的情况下以u为根的子树的欢乐值的最大值 

由题意得u参加聚会的情况下子结点v一定不会参加聚会(有一种情况)

u不参加聚会的情况下子结点v不一定参加聚会(有两种情况)

具体解释如图所示:

 那么,我们可以写出不同情况下的状态转移方程:

当u参加聚会时:dp[u][1]=h[u]+\sum dp[v][0]

当u不参加聚会时:dp[u][0]=\sum max(dp[v][0],dp[v][1])

 其中h【u】代表每个人参加聚会的欢乐值

那么,综合两种情况有:ans=max(dp[rt][0],dp[rt][1])

思路分析完毕,看一下代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn=6060;
vector<int> g[maxn];//存储链式前向星用到动态数组
int n,h[maxn],dp[maxn][2],fa[maxn],rt;//rt为根结点
int a,b;
int dfs(int u)
{
	dp[u][1]=h[u];//初始化
	dp[u][0]=0;
	for(int i=0;i<g[u].size();i++)
	{
		int v=g[u][i];//后继 
		dfs(v);
		dp[u][1]+=dp[v][0];//状态转移方程 
		dp[u][0]+=max(dp[v][1],dp[v][0]);
	} 
	return 	max(dp[u][0],dp[u][1]);
} 

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",h+i);
	}
	for(int i=1;i<n;i++)
	{
		scanf("%d%d",&a,&b);
		fa[a]=b;//定义父节点
		g[b].push_back(a);//压入动态数组 
	}
	for(int i=1;i<=n;i++)//找根结点,根结点是唯一一个没有任何前驱的结点 
	{
		if(!fa[i])
		{
			rt=i;
			break;
		}
	}
	cout<<dfs(rt);

	return 0;
}

2.3  例题2:士兵部署

 这道题和上道题区别是:

上一道题的父节点如果不参加,子结点的状态不确定

这道题的父节点如果参加,子结点的状态不确定

这道题的状态转移方程有:

dp[u][1]=1+\sum min(dp[v][0],dp[v][1])

dp[u][0]=\sum f[v][1]

ans=max(dp[rt][0],dp[rt][1])

 代码(任意选取根结点,这里选取1为根结点):

#include <bits/stdc++.h>
using namespace std;
const int maxn=1510;
int n,dp[maxn][2];
vector<int> g[maxn];

void dfs(int u,int p)//u:当前结点  p:u的父结点 
{
	dp[u][1]=1;
	for(int i=0;i<g[u].size();i++)
	{
		int v=g[u][i];
		if(v==p)  continue;//不能遍历到父结点,以免死循环 
		dfs(v,u);
		dp[u][1]+=min(dp[v][0],dp[v][1]);
		dp[u][0]+=dp[v][1];
	}
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<n;i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		g[a].push_back(b);
		g[b].push_back(a);
	}
	dfs(1,-1);
	printf("%d\n",min(dp[1][0],dp[1][1]));
	return 0;
}

2.4  例题3:强力党逗志芃

 代码:

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

const int maxn=205;
int n,m;
vector<int>g[maxn];
int dp[maxn][maxn];
int arr[maxn];
int fa[maxn];
int root;

void dfs(int u)
{
	int sz=g[u].size();
	for(int k=0;k<sz;k++)
	{
		int v=g[u][k];
		dfs(v);
		for(int i=m-1;i>=0;i--)
		{
			for(int j=0;j<=i;j++)
			{
				dp[u][i]=max(dp[u][i],dp[u][i-j]+dp[v][j]);
			}
		}
	}
	for(int i=m;i>=1;i--)  dp[u][i]=dp[u][i-1]+arr[u];
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++)  cin>>arr[i];
	for(int i=0;i<n-1;i++)
	{
		int x,y;
		cin>>x>>y;
		x--; y--;
		g[x].push_back(y);
		fa[y]=x;
	}
	for(int i=0;i<n;i++)
	{
		if(fa[i]==0)
		{
			root=i;
			break;
		}
	}
	dfs(root);
	printf("%d",dp[root][m]);
	return 0;
}

2.5  例题4:作物杂交(不确定树的结构)

 代码:

#include<bits/stdc++.h>
using namespace std;
int    N, M, K, T;
int arr[2005];//种植时间
int les[2005];//对应位置的作物最短的获得时间
const int INF = 0x3f3f3f3f;
map<int, vector<pair<int, int> > >m;//int与vector<pair<int, int>>一一对应的map数据类型
void DFS(int x) 
{//深度优先
    if (les[x] != -1)  return;//判断是否已经对该作物进行过搜索
    les[x] = 0;
    int minv = INF;
    for (int i = 0; i < m[x].size(); i++)
    {
        int l, r;
        l = m[x][i].first;//获取可以得到x作物的其中一种作物
        r = m[x][i].second;//获取可以得到x作物的另一种作物
        DFS(l), DFS(r);//分别对两个作物进行深度优先搜索
        minv = min(minv, max(les[l], les[r]) + max(arr[l], arr[r]));//比较minv与当前种类的杂交路线的时长的大小
    }
    if (minv != INF)  les[x] += minv;//如果当前的作物可以通过杂交获取
}
int main()
{
    int x, y, z;
    cin >> N >> M >> K >> T;
    for (int i = 1; i <= N; i++)
    {
        cin >> arr[i];
    }
    for (int i = 1; i <= M; i++)
    {
        cin >> x;
    }
    for (int i = 0; i < K; i++)
    {
        cin >> x >> y >> z;
        m[z].push_back({ x,y });
    }
    fill(les + 1, les + N + 1, -1);
    DFS(T);
    cout << les[T] << endl;
    return 0;
}

3  并查集

3.1  简介

并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。这一类问题近几年来反复出现在信息学的国际国内赛题中,其特点是看似并不复杂,但数据量极大,若用正常的数据结构来描述的话,往往在空间上过大,计算机无法承受;即使在空间上勉强通过,运行的时间复杂度也极高,根本就不可能在比赛规定的运行时间(1~3秒)内计算出试题需要的结果,只能用并查集来描述。

并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。

3.2  模板

#include <bits/stdc++.h>
using namespace std;
const int maxn=5e3+10;
int n,m,p;
int fa[maxn];

int init()//初始化 
{
	for(int i=0;i<maxn;i++) fa[i]=i;
}

int find(int x)
{
	while (fa[x] != x) x = fa[x];
	return fa[x];
}

void merge(int a,int b)
{
	a=find(a);
	b=find(b);
	if(a!=b)
	{
		fa[b]=a;//结合到一起,也可以是fa[a]=b;
	}
}

int main()
{
	cin>>n>>m>>p;
	init();//初始化父节点; 
	int u,v;
	while(m--)
	{
		cin>>u>>v;
		merge(u,v);
	}
	while(p--)
	{
		cin>>u>>v;
		u=find(u);
		v=find(v);
		puts(u==v?"Yes":"No");
	}
}

3.3  例题

题目描述

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

小蓝要用七段码数码管来表示一种特殊的文字。

上图给出了七段码数码管的一个图示,数码管中一共有 77 段可以发光的二 极管,分别标记为 a, b, c, d, e, f, g

小蓝要选择一部分二极管(至少要有一个)发光来表达字符。在设计字符 的表达时,要求所有发光的二极管是连成一片的。

例如:b发光,其他二极管不发光可以用来表达一种字符。

例如 c发光,其他二极管不发光可以用来表达一种字符。这种方案与上 一行的方案可以用来表示不同的字符,尽管看上去比较相似。

例如:a, b, c, d, e 发光,f, g不发光可以用来表达一种字符。

例如:b, f 发光,其他二极管不发光则不能用来表达一种字符,因为发光 的二极管没有连成一片。

请问,小蓝可以用七段码数码管表达多少种不同的字符?

方法:并查集+DFS

DFS用来枚举每一种情况,并查集用来检查边界

#include<bits/stdc++.h>
using namespace std;
const int N = 10;
int use[N], ans, e[N][N], fa[N];

int find(int x)
{
	while (fa[x] != x) x = fa[x];
	return fa[x];
}

void merge(int a,int b)
{
	a=find(a);
	b=find(b);
	if(a!=b)
	{
		fa[b]=a;//结合到一起,也可以是fa[a]=b;
	}
}

void dfs(int d)
{
	if(d ==8)
	{
		/* 并查集判是否在同一集合 */
		for(int i = 1;i <= 7;i++)  fa[i] = i;//初始化父亲集合
		for(int i = 1;i <= 7;i++)
		{
			for(int j = 1;j <= 7;j++)
			{
				if(e[i][j] && use[i] && use[j])
				{
					merge(i,j);
				}
			}
		}	
		int k = 0;
		for(int i = 1;i <= 7;i++)
		{
			if(use[i] && fa[i] == i) k++;
		}
		if(k == 1) ans++;//如果所有亮灯都属于同一个集合
		return;
	}
	use[d] = 1;//打开d这个灯,继续开关下一个灯
	dfs(d + 1);
	use[d] = 0;//关闭d这个灯,继续开关下一个灯
	dfs(d + 1);
}

int main()
{
	e[1][2] = e[1][6] = 1;
	e[2][1] = e[2][7] = e[2][3] = 1;
	e[3][2] = e[3][4] = e[3][7] = 1;
	e[4][3] = e[4][5] = 1;
	e[5][4] = e[5][6] = e[5][7] = 1;
	e[6][1] = e[6][5] = e[6][7] = 1;
	e[7][2] = e[7][3] = e[7][5] = e[7][6] = 1;
	dfs(1);
	cout << ans;
	return 0;
}

4  最小生成树(以后更新)

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

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

相关文章

N1盒子使用U外挂HomeAssistant

目录 感谢1.准备工作2.将固件写入U盘&#xff08;32G&#xff09;3.将N1设为U盘启动4.将U盘插入到HDMI旁边的USB接口上5.网页打开HomeAssistant 感谢 HomeAssistant智能家居方案 配套教程 视频 源码 硬件 智能家庭HomeAssistant N1 4月全集成固件 小米米家涂鸦HASS nodered m…

Python图像处理【12】基于小波变换执行图像去噪

基于小波变换执行图像去噪 0. 前言1. 小波变换基础2. 小波变换去噪原理3. 使用 pywt 执行小波变换图像去噪4. 使用 scikit-image 执行小波变换图像去噪4.1 循环旋转技术4.2 改进图像去噪质量 小结系列链接 0. 前言 小波 (wavelets) 变换是表示和分析多分辨率图像的通用方法&am…

上海震坤行工业超市建设数字化采购供应链的实践

上海震坤行工业超市建设数字化采购供应链的实践 对客户而言&#xff0c;MRO工业用品采购一直存在着SKU繁杂、紧急需求多、计划性不强、库存难以管理等特点。有企业统计&#xff0c;MRO零星采购金额占其全类目采购总金额的2%&#xff0c;但是用于管理的时间精力却占到了总体的6…

[使用指南]在使用MyEclipse时如何添加 更新插件

MyEclipse v2022.1.0正式版下载 通过Eclipse市场目录或各种更新站点类型添加插件&#xff0c;可以定制你的MyEclipse IDE(或Angular IDE)。 一、从目录中添加插件 添加额外插件最简单方法是通过Eclipse Marketplace目录。 1. 要打开目录&#xff0c;请从Catalog中选择Help&…

腾讯云服务器网络收发包PPS是什么?性能介绍

什么是网络收发包PPS&#xff1f;云服务器网络收发包PPS多少合适&#xff1f;网络收发包PPS是指云服务器每秒可以处理的网络数据包数量&#xff0c;单位是PPS即packets per second每秒发包数量。云服务器吧来详细说下阿里云服务器网络收发包PPS和腾讯云网络收发包性能参数表&am…

k8s安装部署apollo配置中心

一、文章大纲 二、安装MySQL5.7 三、创建apollo-config 四、创建apollo-admin 五、创建apollo-portal 六、查看apollo各个组件服务状态 七、访问apollo 八、nginx代理配置转发#注意 一定要先启动apollo-config&#xff0c;再启动apollo-admin&#xff0c;最后启动apollo-porta…

什么才是好CDN

选择一种领先于网络和移动技术不断进步以及不断演变的威胁格局的CDN&#xff0c;将使您能够始终如一地为客户提供尽可能好的在线体验&#xff0c;同时最大限度地降低运营复杂性和管理成本。 但问题来了&#xff1a;什么才是最好的CDN&#xff1f; 这个问题的唯一答案是&#x…

HBase高手之路7—HBase之全文检索Phoneix

文章目录 HBase之全文检索Phoenix一、全文检索二、全文检索工具phoenix简介1. 简介2. 使用Phoenix是否会影响HBase性能3. 哪些公司在使用Phoenix4. 官方性能测试4.1 Phoenix对标Hive&#xff08;基于HDFS和HBase&#xff09;4.2 Phoenix对标Impala4.3 关于上述官网两张性能测试…

python基础案例题:进制转换、字符串加密的实现、猜拳游戏、多种方法计算π

目录 前言1.进制转换2.字符串加密的实现3.猜拳游戏4.多种方法计算π尾语 &#x1f49d; 前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 1.进制转换 功能&#xff1a; 获取十进制整数的二进制串&#xff0c;相当于内置函数bin。 算法分析&#xff1a; 对2辗转相除&…

pyecharts从入门到精通-地图专题Map-世界地图和中国城市地图

文章目录 参考安装与查看pyecharts地图实现-Geo数据集查看读取数据生成中文国家名称国家中文和英文名称字典:根据字典&#xff0c;生成国家中文名查看没有转换成功的国家中文有哪些过滤包含中文国家名的数据 可视化人口数据显示中国城市地图数据 拓展-pyecharts中Map源码拓展-p…

开放耳机有什么优缺点,推荐几款不错的开放式耳机

​由于骨传导耳机可以保持耳朵的开放&#xff0c;长时间佩戴不会有闷热感&#xff0c;同时可以在运动中保持安全&#xff0c;因此被越来越多的人接受。在目前市面上骨传导耳机品牌众多&#xff0c;价格从几十元到上千元不等&#xff0c;为了让大家更好地挑选适合自己的骨传导耳…

java获取两个日期之间的所有日期

1、获取日期的过程&#xff1a; 首先创建一个数组&#xff0c;然后在数组的末尾加上一个日期。当我们有两个日期时&#xff0c;可以把这两个日期当做是不同的数组&#xff0c;然后使用 next函数把这两个日期之间的所有时间都获取出来。 2、代码演示&#xff1a; 3、实现效果&am…

bat批处理文件无法执行

执行后弹出cmd窗口&#xff0c;但里面命令未执行 方案一&#xff1a; 1、打开开始菜单——控制面板 2、点击系统和安全——系统 3、点击左上角的“高级系统设置” 4、切换到“高级”选项卡&#xff0c;点击下方的“环境变量” 5、在用户变量下方点击“新建”&#xff0c;…

3.2.3队列的链式实现

队列的链式实现 注意声明队头指针和队尾指针作用 (1)插入节点的时候只要rear指针指向结点的next指针指向的位置&#xff1b; (2)删除只要front指指针指向的头节点next指针指向的位置删除&#xff1b; &#xff08;1&#xff09;初始化&#xff08;带头结点&#xff09; 初试化…

C++:多态的底层实现原理 -- 虚函数表

目录 一. 多态的原理 1.1 虚函数表 1.2 多态的实现原理 1.3 动态绑定与静态绑定 二. 多继承中的虚函数表 2.1 虚函数表的打印 2.2 多继承中虚函数表中的内容存储情况 一. 多态的原理 1.1 虚函数表 对于一个含有虚函数的的类&#xff0c;在实例化出来对象以后&#xff0…

Docker部署SpringBoot+Vue项目

1.项目部署规划 1.后端多模块项目blog以及各模块运行端口&#xff1a; 前台服务模块sangeng-blog->7777&#xff0c;后台服务模块sangeng-admin->8989&#xff0c;公共模块sangeng-framework 2.前端前台Vue项目&#xff1a;sg-blog-vue->80 3.前端后台Vue项目&#x…

如何在AWS EKS上部署安装nginx ingress controller

Ingress Controller Ingress Controller 通常是一个负载均衡器&#xff0c;用于将外部流量路由到您的 Kubernetes 集群&#xff0c;并负责 L4-L7 网络服务 Ingress controller 仅覆盖 L7 流量&#xff0c;而入口重新路由 HTTP 和 HTTPS 流量 Type of Ingress Controllers C…

QT编程集成环境在Ubuntu中如何使用ROS工程?

文章目录 0.引言1.安装Qt Creator&#xff08;带ROS插件&#xff09;2.创建ROS工程3.创建功能包4.创建节点5.添加编译规则6.编译运行 0.引言 在进行ROS开发过程中&#xff0c;会创建许多功能包和源代码文件&#xff0c;这些文件少量时&#xff0c;手动管理还能接受&#xff0c;…

微搭低代码学习之数据收集

低代码和开发之间的关系 低代码平台是一种快速构建应用程序的工具&#xff0c;旨在提高开发效率。它们提供了一种基于图形用户界面的方式来创建应用程序&#xff0c;而无需编写大量的代码。使用低代码平台&#xff0c;开发人员可以更快速地构建和交付应用程序&#xff0c;从而缩…

nginx--HTTPS服务

目录 1.为什么要使用https 2.https协议的实现 1.对称加密 2.非对称加密 3.https加密 3.生成密钥和CA证书需要的依赖 1.查看是否有装openssl 2.查看nginx是否有 --with-http_ssl_module 4.生成密钥和CA证书步骤 步骤一、生成key密钥 步骤二、通过密钥去生成证书签名请求文件…