【图论知识点】【学习笔记】ICM-ICPC程序设计系列-图论及应用——第一章、图【未更新完毕】

来源:互联网 发布:人工智能带来的问题 编辑:程序博客网 时间:2024/05/17 08:59


1.1 图的定义和术语

定义1.1 图:由若干个不同顶点与连接其中某些顶点的边组成的图形称为图。

对于图,通常用一个大写字母G来表示,对于顶点集合,通常用一个大写字母V来表示,对于边的集合,通常用一个大写字母E来表示,并记做G=(V,E)。V中元素的个数也就是顶点的个数,叫做图的阶

1.1.1图的定义、1.1.2 特殊的图

边权:每条路的长度可以作为图上对应边的权值。

点权:每个点的通过费用可以作为图上对应的权值。

定义1.2 :如果图G的点集V只有一个节点,则称G为平凡图。

定义1.3:如果对于图G(V,E)和G2(V,E),G2的顶点集V2是G的顶点集V的一个子集,G2的边集E2是G的边集E的一个子集,那么称G2是G的子图。如果G不等于G2,那么G2是G的真子图。如果V2不等于V,那么G2是G的生成子图。

定义1.4:如果一条边的两端是图中的同一个顶点,称这条边为自环。 

定义1.5:如果图G中没有自环,切每两个顶点之间最多有一条边,那么G称为简单图。

定义1.6:如果图G为简单图并且图中任意两个顶点之间都有一条边,那么G称为完全图。

定义1.7:同构图:图论当中的术语,假设G=(V,E)和G1=(V1,E1)是两个图,如果存在一个双射m:V→V1,使得对所有的x,y∈V均有xy∈E等价于m(x)m(y)∈E1,则称G和G1是同构的,这样的一个映射m称之为一个同构,如果G=G1,则称他为一个自同构、同构具有可逆性,传递性。

定义1.8:补图,定义同补集,如果图G是一个N个顶点的简单图,从N阶完全图中把属于G的边全部去掉之后,得到的图就是G的补图。 

1.1.3 有向图和无向图、1.1.4 路径与联通

定义1.9:如果给图的每条边规定一个方向,那么得到的图称为有向图。相反,边没有方向的图称为无向图。

定义1.10:顶点的度是指与该点相关联的边的条数。有向图的顶点可分入度和出度。顶点v的出边的数目称作顶点v的出度,顶点v入边的数目称作顶点v的入度。无向图中顶点与顶点v相关的边的条数称为顶点v的度。

如果一条路径的起止顶点相同,该路径是“闭”的,称为回路,反之,则称为是“开”的。如果路径中除其实与终点可以重合外,所有顶点两两不等,这样的路径称为简单路径。

定义1.10 在无向图中,如果从顶点v到j有路径,那么称vj连通。

1.2 图的储存结构

1.2.1 邻接矩阵

要将图的信息用C/C++语言来表示,最直接最易理解的储存方式当然非邻接矩阵莫属。那么什么是邻接矩阵呢?

百度百科是这样说滴:是表示顶点之间相邻关系的矩阵。设G=(V,E)是一个图,其中V={v1,v2,…,vn}。

我是这样说滴:就托马的一个二维数组里边存上边权值。e.g:map【i】【j】=1,表示顶点i到顶点j有一条边权值为1的边。相信大家对邻接矩阵的认识还是比较普遍的,这里就不多啰嗦了。

对于邻接矩阵来说,初始化需要O(n^2)的时间,建图需要O(m)[m条边],所以总的时间复杂度是O(n^2)。空间上,邻接矩阵的开销也是O(n^2),与点的个数有关。这里这个方法使用比较常用,所以就不啰嗦了~。

1.2.2 邻接表

邻接表是图的一种链式存储结构。对于图G中每个顶点vi,把所有邻接于vi的顶点vj连接成一个单链表,这个单链表称为顶点vi的邻接表。

邻接表有三种实现方法,分别为动态建表实现,使用STL中的vector模拟链表实现和静态建表实现。这里我记录后两种的实现,因为更加实用和更好理解。

1、STL中的vector模拟链表实现:

#include<stdio.h>#include<vector>using namespace std;#define maxn 1000struct EdgeNode{    int to;    int w;};vector<EdgeNode>map[maxn];int main(){    int i,j,w,n,m,u,v;    EdgeNode e;    scanf("%d%d",&n,&m);    for(int i=0;i<m;i++)    {        scanf("%d%d%d",&u,&v,&w);        e.to=v;        e.w=w;        map[u].push_back(e);    }    printf("yes\n");    for(int i=1;i<=n;i++)    {        printf("i: %d ",i);        for(int j=0;j<map[i].size();j++)        {            printf("j: %d w: %d ",map[i][j].to,map[i][j].w);        }        printf("\n");    }}

2、静态链表(链式前向星)的实现:

#include<stdio.h>#include<string.h>using namespace std;int head[100000];struct EdgeNode{    int to;    int w;    int next;}e[100000];int n,u,v,w,m;int main(){    memset(head,-1,sizeof(head));    scanf("%d%d",&n,&m);    for(int i=0;i<m;i++)    {        scanf("%d%d%d",&u,&v,&w);        e[i].to=v;        e[i].w=w;        e[i].next=head[u];        head[u]=i;    }    for(int i=1;i<=n;i++)    {        printf("from: %d ",i);        for(int k=head[i];k!=-1;k=e[k].next)        {            printf("to:%d quanzhi:%d  ",i,e[k].to,e[k].w);        }        printf("\n");    }}
我们也可以拿数据来测试一下:

8 12
5 8 29
6 1 12
8 3 11
1 2 4
3 1 22
4 3 17
7 4 25
6 5 9
8 7 7
1 6 9
3 2 19
6 7 4












0 0
原创粉丝点击