学习日记(链式前向星)

在写最短路径的时候,看见了需要运用链式前向星的题目;

理解

链式前向星是通过结构体把各个数据连接起来,可以有效减少数据查找的时间,需要引用一个head【】数组,此数组的意义相当于指示标,其数组的下标表示的是需要查找的起始节点,然后又要引入一个结构体,里面包括终止节点和此节点有相同起始节点的下标,所查找的节点的边长,用表格来表示head和结构体就是如下:

结构体数组12345
next(to的好兄弟)00000
to(所查找起始节点的终止节点
wei(边长)
head12345
结构体数组的下标

举一个例子,如果要输入{(1,2,1),(1,3,2),(1,4,2),(2,3,5)}这么一组数据进入上面的表格中;

首先因为head的下标是代表上面结构体数组的下标那么输入(1,2,1)之后,表格中的数据应该是这样的:

结构体数组12345
next(to的好兄弟)00000
to(所查找起始节点的终止节点2
wei(边长)1
head12345
结构体数组的下标1

此时上面表格里的意思就是(先看head,再看结构体数组):和节点一有关系的点要从结构体数组的1号里面去找,那么可以找到to 里面的节点是2,可以知道2和节点1相连接且边长为1,然后再看next,看to有没有兄弟,发现是0,那就是和节点1有关的只有节点2;

然后再把(1,3,2)输入进表格:

结构体数组12345
next(to的好兄弟)01000
to(所查找起始节点的终止节点23
wei(边长)12
head12345
结构体数组的下标2

此时发现第二个输入进去的数据还是关于节点1 的数据,此时表格中的变化规律和第一个差不多,只是next变成了1,还有head[1]变成了2,这就说明我们再去找节点1 的时候要从结构体数组的第二位开始找,那么此时可以找到节点3是和节点1有关系的,那么再看next变成了1,就说明在结构体数组的一号位置还有它的兄弟,那么就查找结构体数组的一号位置,又可以找到节点2。

那么将所有的数据都放入表格后,是这个样子:

结构体数组12345
next(to的好兄弟)01200
to(所查找起始节点的终止节点2343
wei(边长)1225
head12345
结构体数组的下标34

代码实现

struct
{
    int t;
    int next;
    int wei;
}e[num];
//核心代码
void dep(int v1,int v2,int wei)
{
   e[++cnt].t = v2;
   e[cnt].next = head[v1];
   e[cnt].wei = wei;
   head[v1] = cnt;

}
//和dijsktra的结合
void L_dij(int n)
{
    int min;
 while(book[pos]==0)
    {
        min = inf;
        book[pos] = 1;
       for(int i=head[pos];i!=0;i=e[i].next)
       {
           if(book[e[i].t]==0 && dis[e[i].t]>dis[pos]+e[i].wei)
            dis[e[i].t] = dis[pos]+e[i].wei;
       }
       for(int k=1;k<=n;k++)
       {
           if(book[k]==0 && dis[k]<min)
           {
               min = dis[k];
               pos = k;
           }
       }
    }
}

例题

# 【模板】单源最短路径(弱化版)

## 题目背景

本题测试数据为随机数据,在考试中可能会出现构造数据让SPFA不通过,如有需要请移步 [P4779](https://www.luogu.org/problemnew/show/P4779)。

## 题目描述

如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度。

## 输入格式

第一行包含三个整数 $n,m,s$,分别表示点的个数、有向边的个数、出发点的编号。

接下来 $m$ 行每行包含三个整数 $u,v,w$,表示一条 $u \to v$ 的,长度为 $w$ 的边。

## 输出格式

输出一行 $n$ 个整数,第 $i$ 个表示 $s$ 到第 $i$ 个点的最短路径,若不能到达则输出 $2^{31}-1$。

## 样例 #1

### 样例输入 #1

```
4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4
```

### 样例输出 #1

```
0 2 4 3
```

## 提示

【数据范围】    
对于 $20\%$ 的数据:$1\le n \le 5$,$1\le m \le 15$;  
对于 $40\%$ 的数据:$1\le n \le 100$,$1\le m \le 10^4$;   
对于 $70\%$ 的数据:$1\le n \le 1000$,$1\le m \le 10^5$;   
对于 $100\%$ 的数据:$1 \le n \le 10^4$,$1\le m \le 5\times 10^5$,$1\le u,v\le n$,$w\ge 0$,$\sum w< 2^{31}$,保证数据随机。

**Update 2022/07/29:两个点之间可能有多条边,敬请注意。**

对于真正 $100\%$ 的数据,请移步 [P4779](https://www.luogu.org/problemnew/show/P4779)。请注意,该题与本题数据范围略有不同。


样例说明:

![](https://cdn.luogu.com.cn/upload/pic/7641.png)

图片1到3和1到4的文字位置调换

代码

#include<stdio.h>
#define num 1001000

int cnt,book[num],dis[num],head[num];
int inf=2147483647;
int pos;

struct
{
    int t;
    int next;
    int wei;
}e[num];

void initia(int n)
{
    cnt=0;
    for(int i=1;i<=n;i++)
    {
        book[i]=0;
        dis[i]=inf;
        head[i]=0;
    }
    dis[pos]=0;
}

void dep(int v1,int v2,int wei)
{
   e[++cnt].t = v2;
   e[cnt].next = head[v1];
   e[cnt].wei = wei;
   head[v1] = cnt;

}

void L_dij(int n)
{
    int min;
 while(book[pos]==0)
    {
        min = inf;
        book[pos] = 1;
       for(int i=head[pos];i!=0;i=e[i].next)
       {
           if(book[e[i].t]==0 && dis[e[i].t]>dis[pos]+e[i].wei)
            dis[e[i].t] = dis[pos]+e[i].wei;
       }
       for(int k=1;k<=n;k++)
       {
           if(book[k]==0 && dis[k]<min)
           {
               min = dis[k];
               pos = k;
           }
       }
    }
}

int main()
{
    int n,m,s;
    scanf("%d%d%d",&n,&m,&s);
    pos=s;
    initia(m);
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        dep(x,y,z);
    }
    L_dij(n);
    for(int i=1;i<=n;i++)
        printf("%d ",dis[i]);
    printf("\n");
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值