图的总结

思维导图

重要概念的笔记

1.图的定义:图是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。
2.与线性表、树的比较:
(1)线性表中我们把数据元素叫元素,树中将数据元素叫结点,在图中数据元素,我
们则称之为顶点。
(2)线性表中可以没有数据元素,称为空表。树中可以没有结点,叫做空树。在图结构中,不允许没有顶点。
(3)线性表中,相邻的数据元素之间具有线性关系,树结构中,相邻两层的结点具有层次关系,而图中,任意两个顶点之间都可能有关系,顶点之间的逻辑关系用边来表示,边集可以是空的。
3.(1)无向边:若顶点Vi到Vj之间的边没有方向,则称这条边为无向边,用无序偶对(Vi,Vj)来表示。如果图中任意两个顶点之间的边都是无向边,则称该图为无向图。
(2)有向边:若从顶点Vi到Vj的边有方向,则称这条边为有向边,也称为弧。用有序偶<Vi,Vj>来表示,Vj称为弧尾,Vj称为弧头。如果图中任意两个顶点之间的边都是有向边,则称该图为有向图。
4.在无向图中,如果任意两个顶点之间都存在边,则称该图为无向完全图。含有n个顶点的无向完全图有n(n-1)/2条边。
5.在有向图中,如果任意两个顶点之间都存在方向互为相反的两条弧,则称该图为有向完全图。含有n个顶点的有向完全图有n
(n-1)条边。

1.无向图中的极大连通子图称为连通分量。强调:
(1)要是子图;
(2)子图要是连通的;
(3)连通子图含有极大顶点数;
(4)具有极大顶点数的连通子图包含依附于这些顶点的所有边。
2.一个连通图的生成树是一个极小的连通子图,它含有图中全部的n各顶点,但只有足以构成一棵树的n-1条边。
3.如果一个图有n个顶点和小于n-1条边,则是非连通图,如果它多于n-1条边,必定构成一个环。不过有n-1条边并不一定是生成树。
4.如果一个有向图恰有一个顶点的入度为0,其余顶点的入度均为1,则是一棵有向树。

1.图按照有无方向分为无向图和有向图。无向图由顶点和边构成,有向图由顶点和弧构成。弧有弧尾和弧头之分。
2.图按照边或弧的多少分稀疏图和稠密图。如果任意两个顶点之间都存在边叫完全图,有向的叫有向完全图。若无重复的边或顶点到自身的边则叫简单图。
3.图中顶点间存在路径,两顶点存在路径则说明是连通的,如果路径最终回到起始点则称为环,当中不重复叫简单路径。若任意两顶点都是连通的,则图就是连通图,有向则称强连通图。图中有子图,若子图极大连通则就是连通分量,有向则称强连通分量。

1.图的不同存储结构:
(1)邻接矩阵:图的邻接矩阵存储方式是用两个数组来表示图。一个一维数组存储图中顶点信息,一个二维数组(称为邻接矩阵)存储图中的边或弧的信息。
(2)邻接表:数组与链表相结合的存储方法称为邻接表。
2.图的遍历:
(1)需要在遍历过程中把访问过的顶点打上标记,以避免访问多次而不自知。具体办法是设置一个访问数组visited[n],n是图中顶点的个数,初值为0,访问过后设置为1。
(2)深度优先遍历(DFS):
深度优先遍历其实就是一个递归的过程,相当于树的前序遍历。
从图中某个顶点v出发,访问此顶点,然后从v的未访问的邻接点出发深度优先遍历图,直至图中所有和v有路径相通的顶点都被访问到。对于非连通图,只需要对它的连通分量分别进行深度优先遍历。对于n个顶点e条边的图来说,邻接矩阵的方式访问需要O(n2)的时间;对于邻接表来说,需要O(n+e)时间。显然对于点多边少的稀疏图来说,邻接表结构使得算法在时间效率上大大提高。
(3)广度优先遍历(BFS):
类似树的层序遍历。广度优先遍历和深度优先遍历的时间复杂度是一样的。邻接矩阵访问时间为O(n2),邻接表访问时间为O(n+e)。
(4)比较:深度优先遍历更适合目标比较明确,以找到目标为主要目的的情况,而广度优先更适合在不断扩大遍历范围时找到相对最优解的情况。

1、普里姆算法:
以某顶点为起点逐步找各顶点上最小权值得边来构建最小生成树的。
假设N=(P,{E})是连通图,TE是N上最小生成树中边的集合。算法从U={u。}(u。属于V),TE={}开始。重复执行下述操作:在所有u属于U,v属于V-U的边(u,v)属于E中找一条代价最小的边(u。,v。)并入集合TE,同时v。并入U,直至U=V为止。此时TE中必有n-1条边,则T=(V,{TE})为N的最小生成树。
时间复杂度为O(n2)。
2.克鲁斯卡尔算法:
以边为目标去构建。
假设N=(V,{E})是连通图,则令最小生成树的初始状态为只有n个顶点而无边的非连通图T={V,{}},图中每个顶点自成一个连通分量。在E中选择代价最小的边,若该边依附的顶点落在T中不同的连通分量上,则将次变加入到T中,否则舍去此边而选择下一条代价最小的边。依次类推,直至T中所有顶点都在同一连通分量上为止。
克鲁斯卡尔算法的时间复杂度为O(elog2e)。
3.总结:对比两个算法,克鲁斯卡尔算法主要是针对边来展开,边数少时效率会非常高,所以对于稀疏图有很大的优势;而普里姆算法对于稠密图,即边数非常多的情况会更好一些。

1.迪杰斯特拉(Dijkstra)算法:
这是一个按路径长度递增的次序产生最短路径的算法。
时间复杂度为O(n2)。
如果是图中任意一个顶点到另一顶点的距离,时间复杂度为O(n3)。
2.弗洛伊德(Floyd)算法
比较经过顶点的权值,如果经过的顶点路径比原两点间的路径更短,将当前两点间的权值设为更小的一个。时间复杂度为O(n3)。

1.在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网,我们称为AOV网。
2.拓扑排序,其实就是一个有向图构造拓扑序列的过程。构造时会有两个结果,如果此网的全部顶点都被输出,则说明它是不存在环(回路)的AOV网;如果输出顶点数少了,也说明这个网存在环(回路),不是AOV网。
5.拓扑排序算法:
(1)对AOV网进行拓扑排序的基本思路是:从AOV网中选择一个入度为0的顶点输出,然后删去此顶点,并删除以此顶点为尾的弧,继续重复此步骤,直到输出全部顶点或者AOV网中不存在入度为0的顶点为止。
(2)由于拓扑排序的过程中,需要删除顶点,显然用邻接表会更加方便。
(3)拓扑排序的整个算发起的时间复杂度为O(n+e)。
6.AOV网是顶点表示活动的网,它只描述活动之间的制约关系,而AOE网是用边表示活动的网,边上的权值表示活动持续的时间。
7.把路径上各个活动所持续的时间之和称为路径长度,从源点到汇点具有最大长度的路径叫关键路径。

疑难问题及解决方案

7-1 图着色问题 (25分)


刚开始并没有理解题目的意思,不理解图颜色的分配,不知道题目的图如何成立,后来思考知道这就是根据输入的边与点之间的关系,构建一个图,然后再判断两个相连点之间的图着色是否一样且颜色数量是否满足要求。

#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-16 15:23  hhs(黄鸿森)  阅读(230)  评论(0编辑  收藏  举报