定义
不能有自环,无向图任意两个顶点之间不能有两条边
Complete graph:完全图,拥有最大的边数
无向图 E=C(V,2)
有向图 E=2C(V,2)
connected:联通,任意两个顶点都有一条路径相连。
Strongly connected:强联通,对于有向图,任意两个顶点必须有路径使得v->w,w->v
边数最小的联通图是树,E=V-1
Simple path:路径中的点是不同的。
Connected Component:联通分量,即一个图中联通的部分。
degree:度数,一个顶点连接的边数
图的实现
图的实现只需要记录下所有的点的连接情况或者所有的边即可
二维数组(即邻接矩阵)
Graph[a][b] = 1
对于无向图说明a与b相连
对于有向图说明a->b
Graph[a][b] = 0
a,b不联通
显然无向图的矩阵是对称的。
计算v的度数:
无向图:
∑
i
=
0
v
−
1
G
r
a
p
h
[
v
−
1
]
[
i
]
\sum\limits_{i=0}^{v-1}Graph[v-1][i]
i=0∑v−1Graph[v−1][i]
有向图:
∑
i
=
0
v
−
1
G
r
a
p
h
[
v
−
1
]
[
i
]
+
∑
i
=
0
v
−
1
G
r
a
p
h
[
i
]
[
v
−
1
]
\sum\limits_{i=0}^{v-1}Graph[v-1][i]+\sum\limits_{i=0}^{v-1}Graph[i][v-1]
i=0∑v−1Graph[v−1][i]+i=0∑v−1Graph[i][v−1]
对于点的存储方式:索引到底要不要加1,只要自己约定好就可以。
记录带权图:将1改为权重
数组+链表
对于每一个点v,Graph[v]是链表的头
链表的每个元素记录下与其相连的点
计算点的度数:即链表的结点数。(第一个结点不算)
往往会这样实现:
typedef struct AdjVNode *PtrToAdjVNode;
struct AdjVNode{/*一个顶点结点*/
Vertex AdjV;
PtrToAdjVNode Next;
};
typedef struct Vnode{
PtrToAdjVNode FirstEdge;
} AdjList[MaxVertexNum];/*图的数组,指向第一个顶点*/
typedef struct GNode *PtrToGNode;
struct GNode{
int Nv;
int Ne;
AdjList G;
};/*一个图的结点,记录边的个数,点的个数,以及数组*/
typedef PtrToGNode LGraph;
另一种方法是结点记录边:
结点的中记录边的两个点,以及该点的下一条边结点
typedef struct AdjENode{
Vertex Adjv;
PtrToAdjENode vNext;
Vertex Adjw;
PtrToAdjENode wNext;
};
拓扑排序
是一张图所有点的排序。如果两个点之间可能存在顺序a>b,也可能不存在顺序。拓扑排序就是将点按顺序进行排列,只需满足具有的顺序即可。
因此同一张图可能具有多个拓扑序。
比如一张图中有a,b,c三个点,a->b,c->b,则a,c,b和c,a,b都是拓扑序
思路是最前面的点必须满足入度为0,因此先找到一个入度为0的点,将它加入序列,再去掉该点,即将所有和它相邻的点入度减少1。再次循环。
实现:
void Topsort( Graph G )
{ int Counter;
Vertex V, W;
for ( Counter = 0; Counter < NumVertex; Counter ++ ) {
V = FindNewVertexOfDegreeZero( );
if ( V == NotAVertex ) {
Error ( “Graph has a cycle” );
break;
}
TopNum[ V ] = Counter; /* or output V */
for ( each W adjacent to V )
Indegree[ W ] – – ;
}
}
复杂度O(V^2)
上面的方法减少入度以后都需要重新再找入度为0的点,很显然在减少以后判断是否为0,如果是的话可以入队列。不需要下次再从头找一次了。
下面的算法思路是首先所有度数为0的入队列,然后一个点出队列,将与它相邻的点度数减1,如果度数为0,入队列。这样操作直到队列空为止。
void Topsort( Graph G )
{ Queue Q;
int Counter = 0;
Vertex V, W;
Q = CreateQueue( NumVertex ); MakeEmpty( Q );
for ( each vertex V )
if ( Indegree[ V ] == 0 ) Enqueue( V, Q );
while ( !IsEmpty( Q ) ) {
V = Dequeue( Q );
TopNum[ V ] = ++ Counter; /* assign next */
for ( each W adjacent to V )
if ( – – Indegree[ W ] == 0 ) Enqueue( W, Q );
} /* end-while */
if ( Counter != NumVertex )
Error( “Graph has a cycle” );
DisposeQueue( Q ); /* free memory */
}
复杂度O(V+E)
题目
1.In a connected graph, the number of edges must be greater than the number of vertices minus 1.
最小的情况是E=v-1,即树
2.In a directed graph, the sum of the in-degrees must be equal to the sum of the out-degrees of all the vertices.
入度和出度对应一条边的起始和结束,如果出入度不相等说明有一条边只和一个顶点相连。
3.If graph G is NOT connected and has 35 edges, then it must have at least ____ vertices.
因为C(9,2)=36,即9个顶点的连通图最多有36条边,35条边也能符合。C(8,2)=28,即8个顶点的联通图最多有28条边,显然是达不到35条边的,因此如果是不连通的,必须加上一个独立的顶点,9 + 1 = 10
4.A graph with 90 vertices and 20 edges must have at least __ connected component(s).
根据欧拉公式,对于一个联通图 r=v-e+2,r是区域的数量。将一个图的一个联通分量看作一个联通图,假如有k个联通分量,求和可以得到,R=V-E+2k。但是注意到所有联通分量中最外部的那个区域被计算了k次,其实只需计算一次,因此需要减掉。R=V-E+2k-(k-1)=V-E+k+1
这就是任意图都能使用的欧拉公式。
代入可得:k=R+69,为了让联通分量最小,取R=1,即k=70
5.Given an undirected graph G with 16 edges, where 3 vertices are of degree 4, 4 vertices are of degree 3, and all the other vertices are of degrees less than 3. Then G must have at least __ vertices.
根据2e=sum(degree),32=12+12+d*(v-7),其中d<3,因此8<=2(v-7),v>=11