Day3 最短路 最小生成树 拓扑排序
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:
若\(x_1-x_2 \leq3\) , \(2\) 连 \(1\) 有一条权值为 \(3\) 的边,那么
dis[2] =0,dis[1]=0为一组解。若 \(x_1-x_2\leq-3\) , \(2\) 连 \(1\) 有一条权值为 \(-3\) 的边,那么
dis[2]=0,dis[1]=-3就是一组解。如果有正环(权值和为正),比如 \(x_1-x_2<1,x_2-x_3<1,x_3-x_1<1\) 得到 \(0<3\),这是可以的。
如果有负环(权值和为负),比如 \(x_1-x_2<-1,x_2-x_3<-1,x_3-x_1<-1\) 得到 \(0<-3\),这是不可能的。
于是差分约束系统是无解的。
因此,通常由于负权的存在, 差分约束系统 采用 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)。
算法实现
- 维护一个队列,队列中是所有入度为 \(0\) 的点,每次取出一个点(并按次序标号)扫描所有的出边并将这些边删除(将这些点入度\(-1\)),出现新的入度为 \(0\) 的点则加入队,不断重复直到队列为空。
- 点按出队顺序排就是一个拓扑序列,这个序列满足前面的点一定不能被后边的点到达。
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 最短路 最小生成树 拓扑排序的更多相关文章
- [POI2014]RAJ(最短路,拓扑排序)
对于一个点 \(x\) 如何求答案? 由于这个图是个有向无环图,可以先拓扑排序一遍,求出每个点的拓扑序,从起点到它的最长路 \(d2\),从它到终点的最长路 \(d1\).(我写代码是这么写的,注意顺 ...
- 关于最小生成树,拓扑排序、强连通分量、割点、2-SAT的一点笔记
关于最小生成树,拓扑排序.强连通分量.割点.2-SAT的一点笔记 前言:近期在复习这些东西,就xjb写一点吧.当然以前也写过,但这次偏重不太一样 MST 最小瓶颈路:u到v最大权值最小的路径.在最小生 ...
- 牛客寒假训练营3 B 处女座的比赛资格(拓扑排序+最短路)
题目链接 这个题,一眼看上去就是最短路的题,边权有负环显然不能用dij,然后出题人又卡了spfa,,那怎么办的想点办法啊,好像还有一个拓扑排序可以求最短路吧,这时候正解就已经得到了,就是拓扑排序求最短 ...
- bzoj2200拓扑排序+最短路+联通块
自己写的不知道哪里wa了,明明和网上的代码差不多.,. /* 给定一张图,有的边是无向边,有的是有向边,有向边不会出现在环中,且有可能是负权值 现在给定起点s,求出s到其余所有点的最短路长度 任何存在 ...
- [luogu2149][bzoj1880][SDOI2009]Elaxia的路线【拓扑排序+最短路+DP】
题目描述 最近,Elaxia和w的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间. Elaxia和w每天都要奔波于宿舍和实验室之间,他们 希望在节约时间 ...
- [NOIP2017]逛公园 最短路+拓扑排序+dp
题目描述 给出一张 $n$ 个点 $m$ 条边的有向图,边权为非负整数.求满足路径长度小于等于 $1$ 到 $n$ 最短路 $+k$ 的 $1$ 到 $n$ 的路径条数模 $p$ ,如果有无数条则输出 ...
- 算法:图(Graph)的遍历、最小生成树和拓扑排序
背景 不同的数据结构有不同的用途,像:数组.链表.队列.栈多数是用来做为基本的工具使用,二叉树多用来作为已排序元素列表的存储,B 树用在存储中,本文介绍的 Graph 多数是为了解决现实问题(说到底, ...
- 【BZOJ5109】[CodePlus 2017]大吉大利,晚上吃鸡! 最短路+拓扑排序+DP
[BZOJ5109][CodePlus 2017]大吉大利,晚上吃鸡! Description 最近<绝地求生:大逃杀>风靡全球,皮皮和毛毛也迷上了这款游戏,他们经常组队玩这款游戏.在游戏 ...
- BZOJ1880:[SDOI2009]Elaxia的路线(最短路,拓扑排序)
Description 最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间.Elaxia和w**每天都要奔波于宿舍和实验室之间, ...
随机推荐
- Vue3.0工程创建 && setup、ref、reactive函数 && Vue3.0响应式实现原理
1 # 一.创建Vue3.0工程 2 # 1.使用vue-cli创建 3 # 官方文档: https://cli.vuejs.org/zh/guide/creating-a-project.html# ...
- React报错之JSX element type does not have any construct or call signatures
正文从这开始~ 总览 当我们试图将元素或react组件作为属性传递给另一个组件,但是属性的类型声明错误时,会产生"JSX element type does not have any con ...
- 七分钟学会 HTML 网页制作
什么是HTML 点击打开视频讲解更加详细 Hyper Text Markup Language(超文本标记语言) 标签控制排版 体积小,方便传输 编写HTLML 推荐使用:VS Code <!D ...
- GIL互斥锁与线程
GIL互斥锁与线程 GIL互斥锁验证是否存在 """ 昨天我们买票的程序发现很多个线程可能会取到同一个值进行剪除,证明了数据是并发的,但是我们为了证明在Cpython中证 ...
- 以太坊 layer2: optimism 源码学习(二) 提现原理
作者:林冠宏 / 指尖下的幽灵.转载者,请: 务必标明出处. 掘金:https://juejin.im/user/1785262612681997 博客:http://www.cnblogs.com/ ...
- 【深度学习】DNN房价预测
前言 我们使用深度学习网络实现波士顿房价预测,深度学习的目的就是寻找一个合适的函数输出我们想要的结果.深度学习实际上是机器学习领域中一个研究方向,深度学习的目标是让机器能够像人一样具有分析学习的能力, ...
- C# 使用if(DEBUG)调试 失效问题
在调试winform程序的时候,经常会切换debug和release模式.有些时候在debug模式下不想用的东西就会使用 #if(!DEBUG) #endif 但是这次在新项目的时候,使用这个语句,失 ...
- 7个自定义定时任务并发送消息至邮箱或企业微信案例(crontab和at)
前言 更好熟悉掌握at.crontab定时自定义任务用法. 实验at.crontab定时自定义任务运用场景案例. 作业.笔记需要. 定时计划任务相关命令及配置文件简要说明 at 工具 由包 at 提供 ...
- HBase概念入门
HBase简介 HBase基于Google的BigTable论文而来,是一个分布式海量列式非关系型数据库系统,可以提供大规模数据集的实时随机读写. 下面通过一个小场景认识HBase存储.同样的一个数据 ...
- sklearn中MLPClassifier源码解析
神经网络 .fit() 首先传入类私用方法._fit() 确定hidden_layer_size是可迭代的 调用_validate_hyperparameters验证超参数是否合法 验证输入的x和y是 ...