首页 > 其他分享 >第六章 图

第六章 图

时间:2023-09-19 17:34:22浏览次数:30  
标签:连通 struct int 权值 visited 第六章 顶点

一、图的存储及基本操作

邻接矩阵法

#define MaxVertexNum 100 //顶点数目的最大值
typedef char VertexType;//顶点的数据类型
typedef int EdgeType;//带权图中边上权值的数据类型
typedef struct{
	VertexType Vex[MaxVertexNum];//顶点表
	EdgeType Edge[MaxVertexNum][MaxVertexNum];//邻接矩阵,边表
	int vexnum,arcnum; //图的当前顶点数和弧数
}MGraph;

邻接表法

#define MaxVertexNum 100
typedef struct ArcNode{ //边表结点
	int adjvex;//该弧指向的顶点的位置
	struct ArcNode *next;//指向下一条弧的指针
	//InfoType info;//网的边权值
}ArcNode;

typedef struct VNode{ //顶点表结点
	VertexType data;
	ArcNode *first;
}VNode,AdjList[MaxVertexNum];

typedef struct{
	AdjList vertices;//邻接表
	int vexnum,arcnum;
}ALGraph;//邻接表存储的图

二、图的遍历

广度优先搜索BFS

广度优先遍历

bool visited[MAX_VERTEX_NUM];

void BFSTraverse(Graph G)
{
	for(int i = 0;i < G.vexnum;i++)
	{
		visited[i] = false;
	}
	InitQueue(Q);
	//以上为初始化
	for(int i = 0;i < G.vexnum;i++) //BFS遍历整个图
	{
		if(!visited[i])
		{
			BFS(G,i);
		}
	}
}

void BFS(Graph G,int v)
{
	visit(v);
	visited[v] = true;
	EnQueue(Q,v);
	while(!isEmpty(Q))
	{
		DeQueue(Q,v);
		for(w = FirstNeighbor(G,v);w >= 0;w = NextNeighbor(G,v,w)) //出队后不再访问该结点,直接遍历其邻接点
		//NextNeighbor(G,v,w)表示图G中v的除w外的下一个邻接点
		{
			if(!visited[w])//邻接点未访问过,则直接访问并入队
			{
				visit(w);
				visited[w] = true;
				EnQueue(Q,w);
			}
		}
	}
}

广度优先搜索求非带权图的单源最短路

void BFS_MIN_Distance(Graph G,int u)//从u出发的最短路径
{
	//d[i]表示从u到i的最短路径长度
	for(int i = 0;i < G.vexnum;i++)
	{
		d[i] = INF;//初始化
		visited[i] = false;
	}
	d[u] = 0;
	visited[u] = true;
	EnQueue(Q,u);
	while(!isEmpty(Q))
	{
		DeQueue(Q,u);
		for(w = FirstNeighbor(G,u);w >= 0;w = NextNeighbor(G,u,w))//w为u尚未访问的邻接点
		if(!visited[w])
		{
			visited[w] = true;
			d[w] = d[u] + 1;
			EnQueue(Q,w);
		}
	}
}

深度优先搜索DFS

bool visited[MAX_VERTEX_NUM];
void DFSTraverse(Graph G)
{
	for(int i = 0;i < G.vexnum;i++)
	{
		visited[i] = false;
	}
	for(int i = 0;i < G.vexnum;i++)
	{
		if(!visited[i])
		{
			DFS(G,i);
		}
	}
}

void DFS(Graph G,int u)
{
	visit(u);
	visited[u] = true;
	for(w = FirstNeighbor(G,u);w >= 0;w = NextNeighbor(G,u,w))
	{
		if(!visited[w])
		{
			DFS(G,w);
		}
	}
}

三、图的应用

最小生成树

1.Prim算法 O(n^2) 适用于点少边多的图

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 505,INF = 0x3f3f3f3f;
int n,m;
int g[N][N];
int dist[N];//表示点到集合中某点的距离
bool st[N];

int prim()
{
    int res = 0;
    memset(dist,INF,sizeof dist);
    for(int i=0;i<n;i++) //循环n次,把所有点都加入到集合中
    {
        int t = -1;
        for(int j=1;j<=n;j++) //找到集合外距离集合最短的点
        {
            if(!st[j] && (t == -1 || dist[j] < dist[t])) //j在集合外,且未找到任何一个点或j距离较小
            {
                t = j;
            }
        }
        if(i && dist[t] == INF) return INF; //不是第一个点且当前距离最近的点的距离都是无穷,
        //说明图不连通
        if(i) res += dist[t];//只要不是第一条边(无穷),就把t的距离加入到答案去
        
        for(int j=1;j<=n;j++)//用当前新加入的点更新其它集合外的点与集合的距离
        {
            dist[j] = min(dist[j],g[t][j]);
        }
        st[t] = true; //标志着当前点加入到集合中
    }
    return res;
}

int main()
{
    cin>>n>>m;
    memset(g,INF,sizeof g);
    for(int i=0;i<m;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        g[a][b] = g[b][a] = min(c,g[a][b]);//无向图
    }
    int t = prim();
    if(t == INF) puts("impossible");
    else cout<<t<<endl;
    return 0;
}

2.Kruskal算法 O(mlogm) 适用于边少点多的图

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int M = 2e5+20,INF = 0x3f3f3f3f;
int p[M];
int n,m,a,b,c;
struct Edge
{
    int a;
    int b;
    int w;
}edges[M];

int find(int a) //查找a点的集合的祖宗
{
    if(a!=p[a]) p[a] = find(p[a]);
    return p[a];
}
bool cmp(struct Edge a,struct Edge b)
{
    return a.w < b.w;
}

void kruskal()
{
    int cnt = 0,res = 0;
    sort(edges+1,edges+m+1,cmp);//对每个边进行升序排序
    for(int i=1;i<=n;i++) //初始化所有集合
    {
        p[i] = i;
    }
    for(int i=1;i<=m;i++)
    {
        int a = edges[i].a;
        int b = edges[i].b;
        int w = edges[i].w;
        a = find(a),b = find(b); //若不在一个集合,则合并
        if(a!=b)
        {
            p[b] = a;
            cnt++;
            res += w;
        }
    }
    
    if(cnt < n-1) puts("impossible");//合并次数小于n-1,说明图不连通
    else cout<<res<<endl;
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        edges[i] = {a,b,c};
    }
    
    kruskal();

    return 0;
}

最短路

单源最短路 Dijkstra算法 O(n^2)

多源最短路 Floyd算法 O(n^3)

四、易错总结

  • 只要连通图中没有权值相同的边,则其最小生成树唯一
  • 当连通图中存在权值相同的边时,最小生成树不一定唯一
  • 深度优先遍历、拓扑排序、求关键路径可以判断一个有向图是否有环
  • 若一个有向图的顶点不能排成一个拓扑序列,则判定该有向图含有顶点数大于1的强连通分量,不一定是强连通图(如单顶点的图:强连通且存在拓扑序列)
  • 带权图的最小生成树中,某条边的权值可能超过未选边的权值(若错误,则意味着最小生成树一定是权值最小的n-1条边)
  • AOE网中,要缩短工期,必须将所有的关键路径都缩短,即每个关键路径的时间都缩短
  • 上三角邻接矩阵对应的图的拓扑序列必存在但可能不唯一
  • 单个顶点本身可以是强连通的,可以作为一个强连通分量
  • 邻接矩阵主对角元素全为0,无通路的结点元素为无穷
  • 关键路径用顶点序列表示,eg.(v1,v3,v5)
  • 根据工程优先关系及其时间画出AOE图时,最后应把无后继的结点指向时间跨度最长的结点,表明工期的结束
  • Dijkstra算法能给出一棵生成树,但不能给出最小生成树
  • 求有向图的强连通分量的数目的方法类似于拓扑排序:当某个顶点只有出边而没有入边时,其它顶点无法到达这个顶点,不可能于其他顶点构成强连通分量(此时单独构成强连通分量)

标签:连通,struct,int,权值,visited,第六章,顶点
From: https://www.cnblogs.com/zjq182/p/17678070.html

相关文章

  • MySQL篇:第六章_详解mysql视图
    周末有朋友来上海没来得及更新,特此更两篇以正身视图含义:理解成一张虚拟的表视图和表的区别: 使用方式 占用物理空间 视图 完全相同 不占用,仅仅保存的是sql逻辑 表 完全相同 占用视图的好处:1、sql语句提高重用性,效率高2、和表实现了分离,提高了安全性视......
  • linux之路 第六章
    mount命令mount用于挂载文件系统mount设备目录 /安装umount设备名或目录名 //卸载将命令写到/etc/fstab才能永久生效/etc/fstab/dev/sdb2/media/hahaxfsdefaults00挂载操作分区打格 --格式化7 XFS定义: 将一个设备与一个目录去做关联的动作,叫......
  • Evans偏微分方程第六章部分习题参考答案
    2.证明.按定义,\(H_0^1\)上的双线性形式\(B[u,v]=\int_U(a^{ij}u_{x_i}v_{x_j}+cuv)dx\),连续性(即\(|B[u,v]|\lesssim\|u\|_{H_0^1}\|v\|_{H_0^1}\))是显然的.下面看强制性:\[B[u,u]=\int_U(a^{ij}u_{x_i}u_{x_j}+cu^2)dx\]\[\ge\theta\|Du\|_{L^2}^2-\mu\|u\|_{L^2}^2\o......
  • 大型网站技术架构:核心原理与案例分析—第六章:永无止境:网站的伸缩性架构
    1,网站架构的伸缩性设计一般说来,网站的伸缩性设计可分为两类,一类是根据功能进行物理分离实现伸缩;一类是单一功能通过集群实现伸缩。前者是不同的服务器部署不同的服务,提供不同的功能;后者是集群内的多台服务器部署相同的服务,提供相同的功能。1)不同功能进行物理分离实现伸缩每......
  • MongoDB :第六章:Java程序操作MongoDB
    MongoDBJava环境配置在Java程序中如果要使用MongoDB,你需要确保已经安装了Java环境及MongoDBJDBC驱动。本章节实例时候Mongo3.x以上版本。你可以参考本站的Java教程来安装Java程序。现在让我们来检测你是否安装了MongoDBJDBC驱动。首先你必须下载mongojar包,下......
  • 第六章 Sleuth--链路追踪
    6.1链路追踪介绍在大型系统的微服务化构建中,一个系统被拆分成了许多模块。这些模块负责不同的功能,组合成系统,最终可以提供丰富的功能。在这种架构中,一次请求往往需要涉及到多个服务。互联网应用构建在不同的软件模块集上,这些软件模块,有可能是由不同的团队开发、可能使用不同的编......
  • 第六章、web前端架构师
    目录十二、通用上传组件开发以及使用1、导学2、上传组件需求以及开发流程十二、通用上传组件开发以及使用1、导学*开发通用上传组件-通过TDD的方式,开发一个通用上传组件,然后将组件添加到编辑器中进行使用,从这个过程中衍生出很多的相关知识点*主要内容-模......
  • 第六章 项目进度管理
    6.1规划进度管理  规划进度管理是为规划、编制、管理、执行和控制项目进度而制定政策、程序和文档的过程。本过程的主要作用是,为如何在整个项目期间管理项目进度提供指南和方向。本过程仅开展一次或仅在项目的预定义点开展。 进度管理计划l 项目的进度模型l 准确度......
  • Nodejs 第六章(npx)
    npx是什么npx是一个命令行工具,它是npm5.2.0版本中新增的功能。它允许用户在不安装全局包的情况下,运行已安装在本地项目中的包或者远程仓库中的包。npx的作用是在命令行中运行node包中的可执行文件,而不需要全局安装这些包。这可以使开发人员更轻松地管理包的依赖关系,并且可以避免全......
  • 第六章 内建自测试
    1内建自测试概念1.1背景    1.ATE测试成本    2.Memory测试的特殊性Memory内部需要测试的单元多Memory内部单元规整    3.客户对于在线测试的需求:汽车电子的可靠性要求1.2基本流程StartBIST:外部控制信号,开始自测试TestController控制Pa......