1.思维导图
2.重要概念
1.DFS算法
简单的说就是从一个顶点开始,不断的深入访问,当无法访问时再返回到上一级,直到完全访问完。
代码如下:
void DFSTravse(MyGraph& G,int v)//深度优先,采用递归思想,利用邻接表
{
int w;
cout << G.vexs[v]<<" ";
visited[v] = 1;
for (w = 0; w < G.vexNum; w++)
{
if (G.arcs[v][w] != 0 && visited[w] == 0)
DFSTravse(G, w);
}
}
2.BFS算法
简单说,有点类似树的层序遍历,要利用到队列,从一个顶点开始,把它和它邻接的点入队,输出一个邻接点时再把这个邻接点的邻接点入队,直到队空。
代码如下:
void BFS(MyGraph* G, int v) {
for (int i = 1; i <= G->n; i++) visited[i] = 0;//利用邻接表
ArcNode* p;
int t;
queue<int>Q;
printf("%d", v);
visited[v] = 1;
Q.push(v);
while (!Q.empty()) {
t = Q.front();
Q.pop();
p = G->adjlist[t].firstarc;
while (p != NULL) {
if (visited[p->adjvex] == 0) {
printf(" %d", p->adjvex);
visited[p->adjvex] = 1;
Q.push(p->adjvex);
}
p = p->nextarc;
}
}
}
3.最小生成树
1.prim算法
简而言之,核心是利用贪心算法,先从一个顶点开始,选择权值最小的邻接点,把这两个点加入到一个集合中,
再从这两个点中找权值最小的邻接点,再把该邻接点加入到集合中,重复以上操作,直到点全找完。
代码如下:
void MiniSpanTree_Prim(MGragh G)
{
int mini,i,j,k;
int adjvex[MAXVEX];
int lowcost[MAXVEX];
lowcost[0] = 0;
//ps:lowcost[i] = 0
adjvex[0] = 0;
for(i = 0; i < G.numVertexes; i++)
{
lowcost[i] = G.arc[0][i];
adjvex[i] = 0;
}
for(i = 1; i < G.numVertexes; i++)
{
mini = INFITINY;
j = 1;
k = 0;
while(j < G.numVertexes)
{
if(lowcost[j] != 0 && lowcost[j] < mini)
{
mini = lowcost[j];
k = j;
}
j++;
}
printf("(%d %d)",lowcost[k],k);
lowcost[k] = 0;
for(j = 1; j < G.numVertexes; j++)
{
if(lowcost[j] != 0 && G.arc[k][j] < lowcost[j])
{
lowcost[j] = G.arc[k][j];
adjvex[j] = k;
}
}
}
}
2.Kruskal算法
这个算法也是利用贪心算法,描述起来要更简单一些,它是先在所有的边中找权值最小的边,
再从剩下的边中找最小的边,即贪心算法,但是不能出现回路,直到所以点都有边相连。
4.最短路径
这个算法利用了两个数组,即Dist[]和Path[].Dist[]用来记录路径长度,Path[]用来记录每个节点的前驱。
具体方法是从顶点V开始,把到每个节点的路径长度计入Dist[],把每个节点的前驱计入Path[].再从Dist[]里
找路径最小的点,和顶点加入一个集合,接下来从新计算到各点的路径,比原来小的话,就更新两个数组,直到
所以的店都加入集合。
例子:
从而得出最短路径:
5.拓扑排序
找到一个入度为零的点,从这个点开始把它和它的边去掉,再找下一个入度为零的点,重复上述操作,直到所有的点都找完,
就能得到一个拓扑序列,如果最后还有剩余的点就说明该图不是有向无环图。
例如:
这题可以从5开始也可从1开始,然后继续找入度为零的点就行,答案不唯一的。
6.疑难问题及解决方案
图的着色问题
#include<iostream>
using namespace std;
#define MAXVEXNUM 501
//点,边
typedef int ArcCell;
typedef char VexType;
typedef struct {
VexType vexs[MAXVEXNUM];//点的集合
ArcCell arcs[MAXVEXNUM][MAXVEXNUM];//边的集合
int vexNum, arcNum;
int color[MAXVEXNUM];
}MyGraph;
void CreateDGraphFromConsole(MyGraph& G, int vexNum, int arcNum);
int JudgeGraph(MyGraph& G);
int main() {
int n, i, e, k, j, m,t,x;
int min,max;
int V[MAXVEXNUM];
MyGraph G;
cin >> n >> e>>k;
CreateDGraphFromConsole(G, n, e);
cin >> m;
for (i = 0; i < m; i++) {
min = 500;
max = 0;
t = 0;
for (j = 0; j < n; j++) {
cin >> G.color[j];
for (x = 0; x < t; x++) {
if (V[x] == G.color[j])
break;
}
if (x == t) {
V[t++] = G.color[j];
}
}
if (t != k) {
cout << "No" << endl;
}
else {
if (JudgeGraph(G))
cout << "Yes" << endl;
else
cout << "No" << endl;
}
}
}
void CreateDGraphFromConsole(MyGraph& G, int vexNum, int arcNum) {
int i, j, k;
int a,b;
G.vexNum = vexNum;
G.arcNum = arcNum;
for (i = 0; i < vexNum; i++) {
for (j = 0; j < vexNum; j++)
G.arcs[i][j] = 0;
}
for (k = 0; k < arcNum; k++) {
cin >> a >> b;
G.arcs[a-1][b-1] = 1;
G.arcs[b-1][a-1] = 1;
}
}
int JudgeGraph(MyGraph& G) {
int i, j;
for (i = 0; i < G.vexNum; i++) {
for (j = 0; j < G.vexNum; j++) {
if (G.arcs[i][j]) {
if (G.color[i] == G.color[j])
return 0;
}
}
}
return 1;
}
刚开始还不懂,后来老师讲解了,其实就是把邻接矩阵的每一行都遍历过去,看颜色是否重复。