[转]图论-链式向前星

转自:https://blog.csdn.net/hz18790581821/article/details/70233495

我们首先来看一下什么是前向星.

前向星是一种特殊的边集数组,我们把边集数组中的每一条边按照起点从小到大排序,如果起点相同就按照终点从小到大排序,

并记录下以某个点为起点的所有边在数组中的起始位置和存储长度,那么前向星就构造好了.

用len[i]来记录所有以i为起点的边在数组中的存储长度.

用head[i]记录以i为边集在数组中的第一个存储位置.

那么对于下图:

我们输入边的顺序为:

1 2

2 3

3 4

1 3

4 1

1 5

4 5

那么排完序后就得到:

编号:     1      2      3      4      5      6      7

起点u:    1      1      1      2      3      4      4

终点v:    2      3      5      3      4      1      5

得到:

head[1] = 1    len[1] = 3

head[2] = 4    len[2] = 1

head[3] = 5    len[3] = 1

head[4] = 6    len[4] = 2

但是利用前向星会有排序操作,如果用快排时间至少为O(nlog(n))

如果用链式前向星,就可以避免排序.

我们建立边结构体为:

1 struct Edge
2 {
3      int next;
4      int to;
5      int w;
6 };

其中edge[i].to表示第i条边的终点,edge[i].next表示与第i条边同起点的下一条边的存储位置,edge[i].w为边权值.

另外还有一个数组head[],它是用来表示以i为起点的第一条边存储的位置,实际上你会发现这里的第一条边存储的位置其实

在以i为起点的所有边的最后输入的那个编号.

head[]数组一般初始化为-1,对于加边的add函数是这样的:

1 void add(int u,int v,int w)  //链式前向星存图
2 {
3     Node[cnt].v=v;
4     Node[cnt].w=w;
5     Node[cnt].next=head[u];
6     head[u]=cnt++;
7     /*head[u]保存的是以i为起点的所有边中编号最大的那个*/
8 }

初始化cnt = 0,这样,现在我们还是按照上面的图和输入来模拟一下:

edge[0].to = 2;     edge[0].next = -1;      head[1] = 0;

edge[1].to = 3;     edge[1].next = -1;      head[2] = 1;

edge[2].to = 4;     edge[2],next = -1;      head[3] = 2;

edge[3].to = 3;     edge[3].next = 0;       head[1] = 3;

edge[4].to = 1;     edge[4].next = -1;      head[4] = 4;

edge[5].to = 5;     edge[5].next = 3;       head[1] = 5;

edge[6].to = 5;     edge[6].next = 4;       head[4] = 6;

很明显,head[i]保存的是以i为起点的所有边中编号最大的那个,而把这个当作顶点i的第一条起始边的位置.

这样在遍历时是倒着遍历的,也就是说与输入顺序是相反的,不过这样不影响结果的正确性.

比如以上图为例,以节点1为起点的边有3条,它们的编号分别是0,3,5   而head[1] = 5

我们在遍历以u节点为起始位置的所有边的时候是这样的:

for(int i=head[u];~i;i=edge[i].next)

那么就是说先遍历编号为5的边,也就是head[1],然后就是edge[5].next,也就是编号3的边,然后继续edge[3].next,也

就是编号0的边,可以看出是逆序的.

原文地址:https://www.cnblogs.com/ygsworld/p/11216511.html

时间: 2024-10-04 12:11:01

[转]图论-链式向前星的相关文章

图论 ---- spfa + 链式向前星 ---- poj 3268 : Silver Cow Party

Silver Cow Party Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 12674   Accepted: 5651 Description One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbered 1..N is going to attend the big cow party to be held at farm #X (1 ≤ X 

图论 --- spfa + 链式向前星 : 判断是否存在正权回路 poj 1860 : Currency Exchange

Currency Exchange Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 19881   Accepted: 7114 Description Several currency exchange points are working in our city. Let us suppose that each point specializes in two particular currencies and pe

图论 --- spfa + 链式向前星 (模板题) dlut 1218 : 奇奇与变形金刚

1218: 奇奇与变形金刚 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 130  Solved: 37[Submit][Status][Web Board] Description 奇奇 gigi 奇奇口头禅:别人的失败就是我的快乐! 星座:处女座 生日:8月25日 血型:不明 年龄:2岁 生肖:鸡 身高:120公分 体重:149公斤 职业:机器人 兴趣:周游世界 宠物:变形金刚 最喜欢:充电 最讨厌:拔掉它的电源插头 偶像:科学怪人 语言:中文

NYOJ 1274 信道安全【最短路,spfa+链式向前星】

信道安全 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描述 Alpha 机构有自己的一套网络系统进行信息传送.情报员 A 位于节点 1,他准备将一份情报 发送给位于节点 n 的情报部门.可是由于最近国际纷争,战事不断,很多信道都有可能被遭到监 视或破坏. 经过测试分析,Alpha 情报系统获得了网络中每段信道安全可靠性的概率,情报员 A 决定选 择一条安全性最高,即概率最大的信道路径进行发送情报. 你能帮情报员 A 找到这条信道路径吗?  输入 第一行: T 表示以下

POJ #1789 Truck History 最小生成树(MST) prim 稠密图 链式向前星

Description 题目:链接 这道题的数据集网上比较少,提供一组自己手写的数据: INPUT: 3 aaaaaaa baaaaaa abaaaaa OUTPUT: The highest possible quality is 1/2. 思路 题意比较不好理解,简而言之就是有 n 个字符串,设两个字符串之间的差异为 dis,dis 由两个字符串对应位置上不同字母的数量决定.比如串A"aaaaaaa" .串B"baaaaaa" 和串C"abaaaaa&

链式向前星 - 学习理解

学习内容:链式向前星 真的说实话这东西不太难,但是看了一圈博客都讲得好奇怪啊,完全不像在讲东西..好在看了一篇不错的博客:https://www.cnblogs.com/LQ-double/p/5971323.html 第一部分:保存 head[u]记录上一个以u为起点的边, to : 一条边的终点,c:权值,next:同起点的上一条边. int head[MA]; int n,cnt=0; struct node { int to; int c; int next; }edge[MA]; 第二

图论_链式前向星

参考自https://blog.csdn.net/ACdreamers/article/details/16902023(深度理解链式前向星-acdreams) 对于前向星,我的理解就是将边集按照起点顺序进行排序后存储(而并没有将终点也进行排序的必要).同时head[u]记录以u为起点的边集在数组中的第一个(读入时首次出现)存储位置. 前向星的优化:一开始读入时,先算出每个点出去的边有多少条,然后计算出排序后每个点出去的第一条边位置应在哪里,最后把全部边扫一遍放到排序后应在的位置就好了. --摘

hdu2647 逆拓扑,链式前向星。

原文地址 题目分析 题意 老板发工资,但是要保证发的工资数满足每个人的期望,比如A期望工资大于B,只需比B多1元钱即可.老板发的最低工资为888元.输出老板最少发的工资总数,若是无法满足大家的期望,则输出-1. 分析 很明显这是一个拓扑问题,若存在环则无法满足大家的期望.若按常理,A>B,则可能会建立A指向B的有向边.此题不然,因为我们只知道最少的钱数是888,所以从小到大进行拓扑排序更为恰当.所以是建立B指向A的有向边.此之为逆拓扑排序.因为这样处理后排序的结果与原先拓扑排序的顺序相反. 以图

UESTC30-最短路-Floyd最短路、spfa+链式前向星建图

最短路 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的T-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗? Input 输入包括多组数据. 每组数据第一行是两个整数NN ,MM (N≤100N≤100 ,M≤10000M≤1000