树也是一种特殊的图,图上每一个点有出度和入度,对于有向图来说,出度表示顶点的出边,入度表示顶点的入边,图可根据是否有边权分为有权图和无权图,一般来说,对于无权图求最短路时,可以将其赋值为1。可以证明,有向无环图一定存在拓扑序列,因此有向无环图又被成为拓扑图。具体看如下。
建图
邻接矩阵:邻接矩阵通过一个二维数组a[i][j]来存,首先通过memset(a,0x3f,sizeof(a))来给其赋初值为无穷大,每读入一条边就给其赋值为边权值,表示一条边从i指向j,权值为a[i][j],若无向图存两遍即可,时间复杂度和空间复杂度都为O(n^2),不难发现,邻接矩阵存图对时间和空间的消耗都较大,适用于存稠密图,但若是存储稀疏图,会造成大量的空间浪费。故当输入边集较多时,一般不采用邻接矩阵
邻接表:
数组实现
(模板来自于y总,个人感觉这种写法更像链式前向星...?)
// 对于每个点k,开一个单链表,存储k所有可以走到的点。h[k]存储这个单链表的头结点
int h[N], e[N], ne[N], idx;
// 添加一条边a->b
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
// 初始化
idx = 0;
memset(h, -1, sizeof h);
vector实现
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
const int N = 1e3;
int n, m;//n为点数,m为边数
vector<pair<int, int>>h[N]; //N为边的起始点,first为边的入点,second为边的权值
struct node {
int id; int d;//编号和距离
node(){}
node(int id,int d):id(id),d(d){}
//重新建立优先级,实现小根堆
bool operator<(const node& A) const {
return d > A.d;
}
};
int main()
{
cin >> n >> m;
while (m--)
{
int x, y, z;
cin >> x >> y >> z;
h[x].push_back(make_pair(y, z));//有向图的存法
}
}
需要注意的是,因为求最短路时(如dijkstra)需要用到优先队列,但是优先队列默认大根堆,因此需要在结构体中修改他的优先级,将大根堆改为小根堆,但这并不是邻接表存图的主要内容。
链式前向星:
int head[maxn];//表示以i为起点的最后一个点的编号,初始为-1
int cnt = 1;//cnt表示边的编号
struct node {
int v, w, next;//next表示与这条边起点相同的上一条边的编号
}edge[maxn];
void addedge(int u, int v, int w)
{
edge[cnt].v = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt++;
}
//初始化
memset(head, -1, sizeof(head));
/*若要遍历图, i表示点,j首先为以i为起点的最后一个点的编号,j不为 - 1
则证明还有连通的边,j又为与这条边起点相同的上一条边,若遇见-1,则表示
已经没有以i为起点的边了,结束循环,遍历下一个点
*/
for(int i = 0;i < n;i++)
for(int j = head[i];j != -1;j = edge[j].next)
图的遍历
图的深度优先遍历(基于链式前向星建图):
int dfs(int u)
{
st[u] = true; // st[u] 表示点u已经被遍历过
for (int i = head[u]; i != -1; i = edge[i].next)
{
int j = e[i];
if (!st[j]) dfs(j);
}
}
图的宽度优先遍历:
queue<int> q;
st[1] = true; // 表示1号点已经被遍历过
q.push(1);
while (!q.empty())
{
int t = q.front();
q.pop();
for (int i = head[t]; i != -1; i = edge[i].next)
{
int j = edge[i].next;
if (!st[j])
{
st[j] = true; // 表示点j已经被遍历过
q.push(j);
}
}
}
最短路是图论里一个重要的问题,给定一个图,求一条从起点到终点的路径,使得边权和最小。
最短路分为单源最短路径(从某个源点到其他各个顶点的最短距离)和多源最短路径(任意两个顶点之间的最短距离)....
现在是一点三十一分,还是先睡觉算了....