图总结

一、思维导图

二、重要概念

1、 定义:
图(graph):图是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中的顶点的集合,E是图G中边的集合。
2、 基本术语
假设图中有n个顶点,e条边,
则含有e=n(n-1)/2条边的无向图称作完全图;
含有e=n(n-1)条弧的有向图称作有向完全图;
若边或弧的个数e<nlogn,则称作稀疏图,否则称作稠密图。
权(Weight):与图的边或弧相关的数。
网(Network):带权的图。
子图(Subgraph):假设G=(V,{E})和G‘=(V',{E'}),如果V'包含于V且E'包含于E,则称G'为G的子图。
度(TD)、入度(ID)、出度(OD)
顶点的出度:以顶点v为弧尾的弧的数目;
顶点的入度:以顶点v为弧头的弧的数目。
顶点的度(TD)=出度(OD)+入度(ID);
路径、路径长度、回路
设图G=(V,{VR})中的一个顶点序列{u=vi,0,vi,1,…,vi,m=w}中,(vi,j-1,vi,j)VR,1≤j≤m,则称从顶点u到顶点w之间存在一条路径。
路径的长度:路径上的边或有向边(弧)的数目。
简单路径:在一条路径中,没有重复相同的顶点;
回路(环):第一个顶点和最后一个顶点相同的路径;
简单回路(简单环):在一个回路中,若除第一个与最后一个顶点外,其余顶点不重复出现。
连通图、强连通图、生成树
若图G中任意两个顶点之间都有路径相通,则称此图为连通图;
若无向图为非连通图,则图中各个极大连通子图称作此图的连通分量。
若无向图为非连通图,则图中各个极大连通子图称作此图的连通分量
对有向图来说,
若任意两个顶点之间都存在一条有向路径,则称此有向图为强连通图。
否则,其各个强连通子图称作它的强连通分量。
生成树
假设一个连通图有n个顶点和e条边,其中n-1条边和n个顶点构成一个极小连通子图,称该极小连通子图为此连通图的生成树。
对非连通图,则称由各个连通分量的生成树的集合为此非连通图的生成森林。
3、 图的存储结构
邻接矩阵
邻接矩阵存储(存所有边,若不带权则不存在的边包括自己到自己表示为0、若带权则表示为∞)
无向图的邻接矩阵是个对称阵,可以用矩阵的压缩存储。

邻接表存储(存顶点和邻接的边):顺序存储与链式存储相结合。(顶点节点、边节点)
无向图邻接表中顶点节点、边节点数分别为n、2e,有向图的则分别为n、e。故无向图邻接表边节点数为偶数,若边节点数为奇数则为有向图。
有向图 第i行非0元素的个数(邻接矩阵存储)或第i个链表边节点的个数(邻接表存储) 等于该节点的出度OD,所有行非0元素个数和或所有链表边节点个数和等于边数e。
无向图 第i行非0元素的个数(邻接矩阵存储)或第i个链表边节点的个数(邻接表存储) 等于该节点的度TD,所有行非0元素个数和或所有链表边节点个数和等于两倍边数2e。
4、 图的遍历
DFS(深度优先搜索)
深度优先搜索遍历连接图的过程类似树的先根遍历。
深度优先遍历图的实质:对每个顶点查找其邻接点的过程。

void DFSTravse(MyGraph& G, int v)    //深度遍历
{
	int i;
	cout << G.vexs[v] << " ";
	G.visited[v] = 1;
	for (i = 0; i < G.vexNum; i++)
	{
		if (G.arcs[v][i]) {
			if (G.visited[i] == 0) 
				DFSTravse(G, i);
		}
	}
}

BFS(广度优先搜索)
广度优先遍历的实质:通过边或弧找邻接点的过程。

void BFSTravse(MyGraph& G, int v)    //广度遍历
{
	queue<int>q;
	G.visited[v] = 1;
	q.push(v);
	while (!q.empty()) 
	{
		int k = q.front();
		q.pop();
		cout << G.vexs[k] << " ";
		for (int i = 0; i < G.vexNum; i++)
		{
			if (G.arcs[k][i] != 0 && G.visited[i] == 0){
				q.push(i);
				G.visited[i] = 1;
		
	}
		}
	}
}

5、 最小生成树
普里姆(prim)算法
基本思想:
(1)取图中任意一个顶点v作为生成树的根。
(2)往生成树上添加新的顶点w。在添加的顶点w和已经在生成树上的顶点v之间必定存在一条边,并且该边的权值在所有连通顶点v和w之间的边中取值最小。
(3)继续往生成树上添加顶点,直至生成树上含有n个顶点为止。
克鲁斯卡尔(Kruskal)算法
基本思想:
(1)构造一个只含n个顶点的子图SG。
(2)从权值最小的边开始,若他的添加不使SG中产生回路,则在SG上增加这条边
(3)如此重复,直至加上n-1条边为止。
比较两种算法:
普里姆算法:o(n的平方)适用于稠密图。
克鲁斯卡尔算法:适用于稀疏图。
注:
构造的最小生成树不一定唯一,但最小生成树的权值之和一定相同。
6、 最短路径
Dijkstra算法
这是一个按路径长度递增的次序产生最短路径的算法。时间复杂度为O(n2)。
算法实现:

void ShortesPath_DIJ(AMGraph G, int v0) {
	n = G.vexnum;
	for (v = 0; v < n; ++v) {
		s[v] = false;//s初始值为空集
		D[v] = G.arcs[v0][v];//v0到各个顶点的弧的权值
		if (D[v] < MaxInt)
			Path[v] = v0;//v0和v之间有弧
		else Path[v] = -1;//v0和v之间无弧
	}
	S[v0] = true;//v0加入S;
	D[v] = 0;//源点到源点距离为0;
}

弗洛伊德算法(Floyd)
比较经过顶点的权值,如果经过的顶点路径比原两点间的路径更短,将当前两点间的权值设为更小的一个。时间复杂度为O(n3)。

7、 拓扑排序 AOV网 AOE网
拓扑排序:按照有向图给出的次序关系,将图中顶点排成一个线性序列,对于有向图中没有限定次序关系的顶电,则可以人为加上任意的次序关系。由次得到顶点的线性序列称为拓扑有序序列。
AOV网:用顶点表示活动,用弧表示活动间的优先关系的有向图。
注:
(1)AOV网中不应该出现有向环。
(2)对给定的AOV网需先判断网中是否有环。
如何进行拓扑排序:
(1)从有向图中选取一个没有前驱的顶点,并输出之。
(2)从有向图中删去此顶点以及所有以它为尾的弧。
(3)重复上述两步,直至图空,或者图不空但找到无前驱的顶点为止。

关键路径
整个工程的完成时间:从有向图的源点到汇点的最长路径。
关键活动:该弧上的权值增加将使有向图上的最长路径的长度增加。
顶点表示事件;弧表示活动。
事件vi的最早发生时间:从开始点v1到vi的最长路径长度。
事件vi的最迟发生时间:在不推迟整个工期的前提下,事件vi允许发生的最晚时间

三、疑难问题及解决

7-1 图着色问题

#include<iostream>
#include<string>
#include<vector>
#include<set>
using namespace std;
vector<vector<int>>G(501);
int color[501] = { 0 };
bool check(int V)
{
    for (int i = 1; i <= V; i++)
        for (int j = 0; j < G[i].size(); j++)
            if (color[i] == color[G[i][j]])
                return false;
    return true;
}
int main()
{
    int V, E, K, N;
    cin >> V >> E >> K;
    for (int i = 0; i < E; i++)
    {
        int start, end;
        cin >> start >> end;
        G[start].push_back(end);
        G[end].push_back(start);
    }
    cin >> N;
    for (int i = 0; i < N; i++)
    {
        set<int>color_kind;
        for (int j = 1; j <=V; j++)
        {
            cin >> color[j];
            color_kind.insert(color[j]);
        }
        if (check(V) && color_kind.size() == K)
            cout << "Yes" << endl;
        else
            cout << "No" << endl;
    }
    return 0;
}

解决方案:
一开始连题目意思都不清楚,在老师的讲解下逐渐明白题目的思路及要点,然后逐渐写出;

四、总结

遇到问题一开始不懂可以先写思路,然后再写伪代码,再逐步完成代码;

posted @ 2020-05-17 17:34  林毅()  阅读(341)  评论(0编辑  收藏  举报