acm第二十二次图论算法基本概念

    xiaoxiao2022-07-07  145

    基本: 一、什么是图?   很简单,点用边连起来就叫做图,严格意义上讲,图是一种数据结构,定义为:graph=(V,E)。V是一个非空有限集合,代表顶点(结点),E代表边的集合。 二、图的一些定义 (a)有向图:图的边有方向,只能按箭头方向从一点到另一点。( (b)无向图:图的边没有方向,可以双向。 三、图的一些基本概念 结点的度:无向图中与结点相连的边的数目,称为结点的度。 结点的入度:在有向图中,以这个结点为终点的有向边的数目。 结点的出度:在有向图中,以这个结点为起点的有向边的数目。 权值:边的“费用”,可以形象地理解为边的长度。 连通:如果图中结点U,V之间存在一条从U通过若干条边、点到达V的通路,则称U、V 是连通的。 回路:起点和终点相同的路径,称为回路,或“环”。 完全图:一个n 阶的完全无向图含有n*(n-1)/2 条边;一个n 阶的完全有向图含有n*(n-1)条边; 稠密图:一个边数接近完全图的图。 稀疏图:一个边数远远少于完全图的图。 强连通分量:有向图中任意两点都连通的最大子图,特殊地,单个点也算一个强连通分量 三、图的存储结构 1.二维数组邻接矩阵存储 定义int G[101][101]; G[i][j]的值,表示从点i到点j的边的权值,定义如下:

    三、图的存储结构 1.二维数组邻接矩阵存储 定义int G[101][101]; 2.代码参考:下面是建立图的邻接矩阵的参考程序段: int i,j,k,e,n; double g[101][101]; double w; int main() { int i,j; for (i = 1; i <= n; i++) for (j = 1; j <= n; j++) g[i][j] = 0x7fffffff(赋一个超大值); //初始化,对于不带权的图g[i][j]=0,表示没有边连通。这里用0x7fffffff代替无穷大。 cin >> e; for (k = 1; k <= e; k++) { cin >> i >> j >> w; //读入两个顶点序号及权值 g[i][j] = w; //对于不带权的图g[i][j]=1 g[j][i] = w; //无向图的对称性,如果是有向图则不要有这句! } ………… return 0; } 建立邻接矩阵时,有两个小技巧: 初始化数组大可不必使用两重for循环。 ①如果是int数组,采用memset(g, 0x7f, sizeof(g))可全部初始化为一个很大的数(略小于0x7fffffff),使用memset(g, 0, sizeof(g)),全部清为0,使用memset(g, 0xaf, sizeof(g)),全部初始化为一个很小的数。   ②如果是double数组memset(g,127,sizeof(g));可全部初始化为一个很大的数1.38*10306,使用memset(g, 0, sizeof(g))全部清为0. 2.数组模拟邻接表存储   图的邻接表存储法,又叫链式存储法。本来是要采用链表实现的,但大多数情况下只要用数组模拟即可。 #include using namespace std; const int maxn=1001,maxm=100001; struct Edge { int next; //下一条边的编号 int to; //这条边到达的点 int dis; //这条边的长度 }edge[maxm]; int head[maxn],num_edge,n,m,u,v,d; void add_edge(int from,int to,int dis) //加入一条从from到to距离为dis的单向边 { edge[++num_edge].next=head[from]; edge[num_edge].to=to; edge[num_edge].dis=dis; head[from]=num_edge; } int main() { num_edge=0; scanf("%d %d",&n,&m); //读入点数和边数 for(int i=1;i<=m;i++) { scanf("%d %d %d",&u,&v,&d); //u、v之间有一条长度为d的边 add_edge(u,v,d); } for(int i=head[1];i!=0;i=edge[i].next) //遍历从点1开始的所有边 { //… } //… return 0; }

    最新回复(0)