Day3 最短路 最小生成树 拓扑排序

(一)最短路

一、多源最短路

从任意点出发到任意点的最短路

1. Floyd \(O(n^3)\)

for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
Edge[i][j]=min(Edge[i][j],Edge[i][k]+Edge[k][j]);

2. 拓展:传递闭包

在图中,给定若干元素和若干对二元关系,且关系具有传递性。“通过传递性推导出尽量多的元素之间的关系”的问题称为传递闭包。

传递性:设 \(\odot\) 是定义在集合 \(S\) 上的二元关系,若对于任意 \(a,b,c \in S\),只要有 \(a \odot b\) 且 \(b \odot c\),就必然有 \(a \odot c\),则称关系 \(\odot\) 具有传递性

for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
can[i][j]|=can[i][k]&can[k][j];

二、单源最短路

从一个点出发到所有点的最短路

1. Dijkstra

①Dijkstra \(O(n^2)\)
void dijkstra(int x)
{
for(int i=1;i<=t;i++)
dis[i]=INF;
dis[x]=0,vis[x]=true;
for(int i=Link[x];i!=0;i=Edge[i].nxt)
{
int y=Edge[i].y;
dis[y]=Edge[i].vis;
}
for(int i=1;i<=t;i++)
{
int f,minn=INF+10;
for(int j=1;j<=t;j++)
{
if(!vis[j]&&dis[j]<minn)
{
minn=dis[j];
f=j;
}
}
vis[f]=true;
for(int i=Link[f];i!=0;i=Edge[i].nxt)
{
int y=Edge[i].y;
if(!vis[y]) dis[y]=min(dis[y],Edge[i].vis+dis[f]);
}
}
}
②堆优化 Dijkstra \(O(m \log n)\)
priority_queue<node> q;
bool operator < (node n1,node n2)
{
return n1.dis>n2.dis;
}
void dijkstra(int st)
{
for(int i=1;i<=n;i++)
dis[i]=INF;
dis[st]=0;
q.push({0,st});
while(!q.empty())
{
int x=q.top().i;
q.pop();
if(vis[x]) continue;
vis[x]=1;
for(int j=Link[x];j!=0;j=Edge[j].nxt)
{
int y=Edge[j].y,val=Edge[j].val;
if((long long)dis[x]+val<dis[y])
{
dis[y]=dis[x]+val;
q.push({dis[y],y});
}
}
}
}

2. SPFA \(O(km \sim nm)\)

解决负环判断/差分约束问题。

void SPFA(int st)
{
queue<int> q;
for(int i=1;i<=n;i++)
dis[i]=INF;
dis[st]=0;
q.push(st);
while(!q.empty())
{
int x=q.front();
q.pop();
vis[x]=false;
for(int i=Link[x];i;i=Edge[i].nxt)
{
int y=Edge[i].y,val=Edge[i].val;
if(dis[x]+val<dis[y])
{
dis[y]=dis[x]+val;
if(!vis[y])
{
q.push(y);
vis[y]=1;
}
}
}
}
}

3. 拓展:查分约束

差分约束系统是一种特殊的 \(N\) 元一次不等式组。

它包含 \(N\) 个变量 \(X_1 \sim X_N\) 以及 \(M\) 个约束条件,每个约束条件都是由两个变量作差构成的,形如 \(X_i-X_j \leq C_k\) ,其中 \(C_k\) 是常数。我们要解决的问题是:

求一组解 \(X_1 = a_1, X_2 = a_2,\cdots, X_N = a_N\),使得所有约束条件得到满足。

我们把不等式 \(X_i-X_j\leq C_k\) 变为 \(X_i\leq X_j+C_k\) ,这和我们单源最短路里 \(dis[y]\leq dis[x]+z\) 非常相似。

**因此,可以把 \(X_i\) 看作有向图中的一个点 \(i\),对于每个条件 \(X_i-X_j\leq C_k\),从节点 \(j\) 向节点 \(i\) ,连一条长度为 \(C_k\) 的有向边。 **

如果 \(a_1,a_2,\cdots,a_n\) 是该差分约束系统的一组解,那么对于任意的常数 \(D\),\(a_1+D,\cdots,a_n+D\) 显然也是该差分约束系统的一组解,因为这样做差后 \(D\) 刚好被消掉。

所以不妨先求一组负数解,假设 \(\forall x_i\leq 0\) ,添加一个 \(0\) 号节点,\(x_0=0\) ,即有 \(x_i-x_0\leq 0\),

设 \(dis[0]=0\),从 \(0\) 开始跑单源最短路,若图中存在负环,则给定的差分约束系统无解;否则, \(x_i=dis_i\) 为该差分约束系统的一组解。

Example:

  1. 若\(x_1-x_2 \leq3\) , \(2\) 连 \(1\) 有一条权值为 \(3\) 的边,那么 dis[2] =0,dis[1]=0 为一组解。

  2. 若 \(x_1-x_2\leq-3\) , \(2\) 连 \(1\) 有一条权值为 \(-3\) 的边,那么 dis[2]=0,dis[1]=-3 就是一组解。

  3. 如果有正环(权值和为正),比如 \(x_1-x_2<1,x_2-x_3<1,x_3-x_1<1\) 得到 \(0<3\),这是可以的。

  4. 如果有负环(权值和为负),比如 \(x_1-x_2<-1,x_2-x_3<-1,x_3-x_1<-1\) 得到 \(0<-3\),这是不可能的。

  5. 于是差分约束系统是无解的。

因此,通常由于负权的存在, 差分约束系统 采用 SPFA 来求解,以及判断负环。

4. 总结

单源最短路首选稳定的 堆优化Dijkstra ,其次是 SPFA

很多时候简单的 \(\text{SPFA}\) 甚至更快,但我们知道 \(\text{Dijkstra}\) 是不能处理有负权边的图的。

所以有负权的时候,我们常用 SPFA

(二)最小生成树

一、Kruskal \(O(mlogn)\)

将边排序,利用并查集从小到大加入能够联通新的联通分量的边。

void Kruskal()
{
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=1;i<=m;i++)
{
int fx,fy;
fx=getfather(a[i].a);
fy=getfather(a[i].b);
if(fx!=fy)
{
merge(fx,fy);
flag[i]=1;
if(++cnt==n-1) break;
}
}
}

二、Prim \(O((n+m)logn)\)

将点划分,利用 堆(优先队列) 以生成树到散点的边的边权为关键字,从小到大加入点。

void Prim()
{
for(int i=1;i<=n;i++)
dis[i]=Edge[1][i];
vis[1]=true;
for(int i=1;i<=n-1;i++)
{
int minn=INF,f;
for(int j=1;j<=n;j++)
{
if(!vis[j]&&dis[j]<minn)
{
minn=dis[j];
f=j;
}
}
vis[f]=true;
ans+=minn;
for(int j=1;j<=n;j++)
if(!vis[j]&&Edge[f][j]&&dis[j]>Edge[f][j])
dis[j]=Edge[f][j];
}
}

(三)拓扑排序

给一个图的所有点排序,使得排在前面的点不依赖于后边

用于判断图中是否有环,判断图是否是一个链(都是简单 bfs)。

算法实现

  1. 维护一个队列,队列中是所有入度为 \(0\) 的点,每次取出一个点(并按次序标号)扫描所有的出边并将这些边删除(将这些点入度\(-1\)),出现新的入度为 \(0\) 的点则加入队,不断重复直到队列为空
  2. 点按出队顺序排就是一个拓扑序列,这个序列满足前面的点一定不能被后边的点到达
void topsort()
{
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=Link[x];i;i=Edge[i].nxt)
{
int y=Edge[i].y;
f[y]+=f[x]%Mod;
ind[y]--;
if(!ind[y]) q.push(y);
}
}
}

Day3 最短路 最小生成树 拓扑排序的更多相关文章

  1. [POI2014]RAJ(最短路,拓扑排序)

    对于一个点 \(x\) 如何求答案? 由于这个图是个有向无环图,可以先拓扑排序一遍,求出每个点的拓扑序,从起点到它的最长路 \(d2\),从它到终点的最长路 \(d1\).(我写代码是这么写的,注意顺 ...

  2. 关于最小生成树,拓扑排序、强连通分量、割点、2-SAT的一点笔记

    关于最小生成树,拓扑排序.强连通分量.割点.2-SAT的一点笔记 前言:近期在复习这些东西,就xjb写一点吧.当然以前也写过,但这次偏重不太一样 MST 最小瓶颈路:u到v最大权值最小的路径.在最小生 ...

  3. 牛客寒假训练营3 B 处女座的比赛资格(拓扑排序+最短路)

    题目链接 这个题,一眼看上去就是最短路的题,边权有负环显然不能用dij,然后出题人又卡了spfa,,那怎么办的想点办法啊,好像还有一个拓扑排序可以求最短路吧,这时候正解就已经得到了,就是拓扑排序求最短 ...

  4. bzoj2200拓扑排序+最短路+联通块

    自己写的不知道哪里wa了,明明和网上的代码差不多.,. /* 给定一张图,有的边是无向边,有的是有向边,有向边不会出现在环中,且有可能是负权值 现在给定起点s,求出s到其余所有点的最短路长度 任何存在 ...

  5. [luogu2149][bzoj1880][SDOI2009]Elaxia的路线【拓扑排序+最短路+DP】

    题目描述 最近,Elaxia和w的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间. Elaxia和w每天都要奔波于宿舍和实验室之间,他们 希望在节约时间 ...

  6. [NOIP2017]逛公园 最短路+拓扑排序+dp

    题目描述 给出一张 $n$ 个点 $m$ 条边的有向图,边权为非负整数.求满足路径长度小于等于 $1$ 到 $n$ 最短路 $+k$ 的 $1$ 到 $n$ 的路径条数模 $p$ ,如果有无数条则输出 ...

  7. 算法:图(Graph)的遍历、最小生成树和拓扑排序

    背景 不同的数据结构有不同的用途,像:数组.链表.队列.栈多数是用来做为基本的工具使用,二叉树多用来作为已排序元素列表的存储,B 树用在存储中,本文介绍的 Graph 多数是为了解决现实问题(说到底, ...

  8. 【BZOJ5109】[CodePlus 2017]大吉大利,晚上吃鸡! 最短路+拓扑排序+DP

    [BZOJ5109][CodePlus 2017]大吉大利,晚上吃鸡! Description 最近<绝地求生:大逃杀>风靡全球,皮皮和毛毛也迷上了这款游戏,他们经常组队玩这款游戏.在游戏 ...

  9. BZOJ1880:[SDOI2009]Elaxia的路线(最短路,拓扑排序)

    Description 最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间.Elaxia和w**每天都要奔波于宿舍和实验室之间, ...

随机推荐

  1. GTID主从和lamp架构运行原理

    目录 GTID主从 GTID概念介绍 GTID工作原理 GTID主从配置 lamp lamp简介 web服务器工作流程 cgi与fastcgi http协议 是什么? lamp架构运行的原理 Apac ...

  2. (一)esp32开发环境搭建(VSCode+IDF实现单步调试)

    保姆级手把手教学视频 https://www.bilibili.com/video/BV1RL411A7CU 前言 因为碰上一个学长,跟他聊了会儿天,推荐我做一点物联网的项目,想来想去,那就用WiFi ...

  3. Luogu3275 [SCOI2011]糖果 (差分约束)

    逆序建超级源快十倍还行 #include <cstdio> #include <iostream> #include <cstring> #include < ...

  4. 记一次 ClickHouse 性能测试

    前言 在工作场景中,我们会采集工厂设备数据用于智能控制,数据的存储用了 InfluxDB,随着数据规模越来越大,InfluxDB 的性能越来越差,故考虑引入 ClickHouse 分担 InfluxD ...

  5. 283. 移动零--LeetCode__双指针

    来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/move-zeroes 著作权归领扣网络所有.商业转载请联系官方授权,非商业转载请注明出处. 思路 用一 ...

  6. 刷题记录:Codeforces Round #734 (Div. 3)

    Codeforces Round #734 (Div. 3) 20210920.网址:https://codeforces.com/contest/1551. 编程细节:下标定义不要一会[1,n]一会 ...

  7. HC32L110(三) HC32L110的GCC工具链和VSCode开发环境

    目录 HC32L110(一) HC32L110芯片介绍和Win10下的烧录 HC32L110(二) HC32L110在Ubuntu下的烧录 HC32L110(三) HC32L110的GCC工具链和VS ...

  8. UIView Animation 动画学习总结

    目录 一.前言 二.UIView Animation 2.1 简单动画 2.2 关键帧动画 2.3 View 的转换 三.CALayer Animation 3.1 基本动画(CABasicAnima ...

  9. 闭包 与 js内存管理

    参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Memory_Management            https://blog ...

  10. KingbaseES 工具sys_dump,sys_restore使用介绍

    说明: KingbaseES V8R6版本中自带数据库备份导出sys_dump,和备份恢复sys_restore工具. sys_dump:把KingbaseES数据库抽取为一个脚本文件或其他归档文件. ...