首页 > 其他分享 >图论初步

图论初步

时间:2023-02-26 21:57:39浏览次数:28  
标签:rll 图论 read ll 初步 dijkstra dis define

最短路

前置

在本文最短路模块中, \(n\) 代表点数, \(m\) 代表边数。

图分稠密图和稀疏图,稀疏图 \(m≈n×10\) ,稠密图 \(m≈n^2\) 。

对于每个算法的代码,写在函数内的是核心代码。

floyd

floyd 是一种基于动态规划思想的全源最短路算法,可以解决负权边,复杂度 \(\operatorname{O(n^3)}\) 。

思路

状态表示:

设 \(dis_{(i,j)}\) 为 \(i\) 到 \(j\) 的的短距离。

三层循环:

  1. 第一层 \(k\) 枚举阶段,表示当前对于每个点已经确定离它 \(k\) 个点的最短路径。
  2. 第二层 \(i\) 枚举起点,表示从第 \(i\) 个点开始的最短路径。
  3. 第三层 \(j\) 枚举终点,表示从第 \(j\) 个点结束的最短路径。

状态转移:

一条路有两种走法:

  1. 直接从 \(i\) 走到 \(j\) : \(dis_{(i,j)}\) 。
  2. 先从 \(i\) 走到 \(k\) 再从 \(k\) 走到 \(j\) : \(dis_{(i,k)}+dis_{(k,j)}\) 。

image

floyd 算法的思路就是,对于所有的 \(i,j,k\) ,取这两条路的最短距离。

dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);

代码

#include <bits/stdc++.h>
#define ll long long
#define rll register ll
#define cll const ll
#define N 1005
using namespace std;
inline ll read()
{
    rll x=0;bool f=1;register char c=getchar();
    while(c<48||c>57){if(c=='-') f=0;c=getchar();}
    while(c>=48&&c<=57){x=x*10+(c^48);c=getchar();}
    return f?x:-x;
}
inline void write(ll x)
{
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+48);
}
cll n=read();
ll m=read(),a,b,c,dis[N][N];
inline void floyd()
{
    for(rll k=1;k<=n;k++)
        for(rll i=1;i<=n;i++)
            for(rll j=1;j<=n;j++)
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
int main()
{
    memset(dis,0x3f,sizeof dis);
    for(rll i=1;i<=n;i++) dis[i][i]=0;
    //初始化所有变为正无穷,每个点到自己的最短距离为 0
    while(m--)
    {
        a=read(),b=read(),c=read();
        dis[a][b]=min(dis[a][b],c);
        dis[b][a]=min(dis[b][a],c);
        //无向边,双向连边即可
        //如有重边,保留最小值即可
    }
    floyd();
    for(rll i=1;i<=n;i++)
    {
        for(rll j=1;j<=n;j++)
        {
            if(dis[i][j]>=0x3f3f3f3f3f3f3f3f) cout << "-1";
            else write(dis[i][j]),putchar(' ');
            //如果为正无穷就无法走到
            //注意 memset 是以字节赋值的,因此对于 long long 是 0x3f3f3f3f3f3f3f3f
        }
        putchar('\n');
    }
    return 0;
}

dijkstra

dijkstra 是一种基于贪心思想的单源最短路算法,不能解决负权边,朴素版复杂度 \(\operatorname{O(n^2)}\) ,堆优化版复杂度 \(\operatorname{O(mlogn)}\) 。

思路

执行 \(n-1\) 轮循环,每轮循环先寻找全局最小值,再用全局最小值更新起点到每个点的距离 \(dis_{i}\) 。
至于为什么是 \(n-1\) 轮,是因为跑完 \(n-1\) 轮后,点只剩下一个,最短路已经确定。

代码

#include <bits/stdc++.h>
#define ll long long
#define rll register ll
#define cll const ll
#define N 505
#define M 100005
using namespace std;
inline ll read()
{
    rll x=0;bool f=1;register char c=getchar();
    while(c<48||c>57){if(c=='-') f=0;c=getchar();}
    while(c>=48&&c<=57){x=x*10+(c^48);c=getchar();}
    return f?x:-x;
}
inline void write(ll x)
{
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+48);
}
cll n=read();
ll m=read(),dis[N],g[N][N];
bool flag[N];//flag[i] 表示每个点是否被取用过
inline void dijkstra()
{
    memset(dis,0x3f,sizeof(dis));
    dis[1]=0;
    for(rll i=0;i<n;i++)
    {
        rll t=-1;
        for(rll j=1;j<=n;j++)
            if(!flag[j]&&(t==-1||dis[j]<dis[t])) t=j;
        //寻找全局最小值
        flag[t]=1;
        for(rll j=1;j<=n;j++) dis[j]=min(dis[j],dis[t]+g[t][j]);
        //用全局最小值更新剩余的点
    }
}
int main()
{
    memset(g,0x3f,sizeof(g));
    while(m--)
    {
        cll a=read(),b=read(),c=read();
        g[a][b]=min(g[a][b],c);//重边取最小值
    }
    dijkstra();
    if(dis[n]>=0x3f3f3f3f3f3f3f3f) cout << "-1";
    else write(dis[n]);
    //如果距离为正无穷说明不存在路径
    return 0;
}

堆优化 dijkstra

我们发现,朴素 dijkstra 算法的瓶颈在于寻找全局最小值

标签:rll,图论,read,ll,初步,dijkstra,dis,define
From: https://www.cnblogs.com/wangxuzhou-blog/p/17157859.html

相关文章

  • C#初步学习1(个人笔记,基于老赵.Net的视频自学,不喜勿喷)
    //此笔记仅针对个人学习而写,会有所缺失的内容,不喜勿喷初步学习创建文件这里使用VisualStudio编写C#代码安装其中一个运行平台,创建新项目至于名字那就起每一个码农的......
  • Android-简单增删改查-初步实现主要页面
    我先想做出个简单增删改查连上数据库,能把学生姓名列出来,可以添加学生数据今天时间很紧,搁宿舍敲了半天把页面写出来了,剩下的代码还不少,一口气也做不完,我也有点熬不住了。......
  • Django 初步运行过程分析笔记
    2.django运行过程分析第一个过程分析:django启动过程pythonmangage.pyrunserver0.0.0.0:8000这个命令先被python的sys.argv接收起来,保存成[mangage.py,runserver,0.0......
  • 【JavaScript】25_数组初步
    1、简介数组(Array)数组也是一种复合数据类型,在数组可以存储多个不同类型的数据数组中存储的是有序的数据,数组中的每个数据都有一个唯一的索引可以通过索引来操作获取数据数......
  • 计算机的初步认识
    计算机的初步认识计算机广泛应用在:科学计算,数据处理,自动控制,计算机辅助设计,人工智能,网络等领域冯.诺伊曼体系结构......
  • Ubuntu环境初步搭建
    用虚拟机把Ubuntu系统给装好后,一般我们会进行什么配置操作呢?【不按顺序,按需设置】安装远程工具【可用第三方工具(CRT、xshell)等去连接Linux】apt-getinstallopenssh......
  • Docker的初步认识,安装与基本操作
    一、Docker概述1、Docker的概念•Docker是一个开源的应用容器引擎,基于go语言开发并遵循了apache2.0协议开源•Docker是在Linux容器里运行应用的开源工具,是一种轻量级......
  • B - Learning Languages【2022级专题三图论课后练习】
    B-LearningLanguages原题链接思路由于可以传译,所以可以将共同语言(包括传译)者视为一个集合(合并),最后查询总共集合数-1就是答案注意特判:有可能有公司所有人一种语言都......
  • A - 并查集【2022级专题三图论课后练习】
    A-并查集思路模板注意01串的处理代码点击查看代码#include<iostream>usingnamespacestd;#defineXfirst#defineYsecondtypedefpair<int,int>pii;......
  • 群论初步
    引入在数学和抽象代数中,群论(GroupTheory)主要研究叫做「群」的代数结构。定义在数学中,群(group)是由一种集合以及一个二元运算所组成的,符合「群公理」的代数结构。一个群......