图论-最短路个人总结
差分约束
如若一个系统由n个变量和m个不等式组成,并且这m个不等式对应的系数矩阵中每一行有且仅有一个1和-1,其它的都为0,这样的系统称为差分约束( difference constraints )系统
对
于
形
如
:
B
−
A
<
=
c
⋯
(
1
)
C
−
B
<
=
a
⋯
(
2
)
C
−
A
<
=
b
⋯
(
3
)
对于形如:\\ B-A<=c\cdots (1)\\ C-B<=a\cdots (2)\\ C-A<=b\cdots (3)\\
对于形如:B−A<=c⋯(1)C−B<=a⋯(2)C−A<=b⋯(3)
我们要知道
C
−
A
C-A
C−A的最大值,即
C
−
A
<
=
T
C-A<=T
C−A<=T中
T
T
T的值。通过
(
1
)
+
(
2
)
(1)+(2)
(1)+(2),可以得到
C
−
A
<
=
a
+
c
C-A<=a+c
C−A<=a+c,所以这个问题就是求。对于
B
−
A
<
=
c
B-A<=c
B−A<=c 来说,等价于
B
<
=
c
+
A
B<=c+A
B<=c+A,类似于求最短路中的松弛操作if(dis[u]+w<dis[v]) dis[v]=dis[u]+w
,松弛操作的目的就是尽可能使dis[u]+w>=dis[v],所以求
T
T
T的值就是求A~>B,B~>C,A~>C,所形成的有向图中A~>C的最短路径
相反的若形如以下:
对
于
形
如
:
B
−
A
>
=
c
⋯
(
1
)
C
−
B
>
=
a
⋯
(
2
)
C
−
A
>
=
b
⋯
(
3
)
对于形如:\\ B-A>=c\cdots (1)\\ C-B>=a\cdots (2)\\ C-A>=b\cdots (3)\\
对于形如:B−A>=c⋯(1)C−B>=a⋯(2)C−A>=b⋯(3)
并求
C
−
A
C-A
C−A的最小值,即
C
−
A
>
=
T
C-A>=T
C−A>=T中
T
T
T的值,也就是求上图中C~>A的最长路径。
若有形如
A
−
B
=
c
A-B=c
A−B=c的等式,可以转化为
c
<
=
A
−
B
<
=
c
c<=A-B<=c
c<=A−B<=c,即
A
−
B
<
=
c
,
B
−
A
<
=
−
c
A-B<=c,B-A<=-c
A−B<=c,B−A<=−c
若是整数规划,且有形如
A
−
B
<
c
A-B<c
A−B<c,可以转化为
A
−
B
<
c
−
1
A-B<c-1
A−B<c−1
Dijkstra算法
void Dijkstra(int n,int r){
memset(dis,INF,sizeof(dis));dis[r]=0;
priority_queue<node>q;
q.push(node(r,0));
while(!q.empty()){
node now=q.top();q.pop();
int &u=now.v;
if(vis[u]) continue;vis[u]=1;
for(int i=head[u];~i;i=g[i].next){
int &v=g[i].v,&w=g[i].w;
if(!vis[v]&&dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
q.push(node(v,dis[v]));
}
}
}
}
SPFA算法
bool SPFA(int n,int r){
memset(dis,INF,sizeof(dis));dis[r]=0;
memset(vis,0,sizeof(vis));vis[r]=1;
memset(ccnt,0,sizeof(ccnt));ccnt[r]=1;
queue<int>q;q.push(r);
while(!q.empty()){
int u=q.front();q.pop();vis[u]=0;
for(int i=head[u];~i;i=g[i].next){
int &v=g[i].v,&w=g[i].w;
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
if(!vis[v]){
q.push(v);vis[v]=1;
if(++ccnt[v]>n) return 1;
}
}
}
}
return 0;
}
Bellman_ford算法
bool Bellman_ford(int n,int r){
memset(dis,0,sizeof(dis));dis[r]=0;
for(int i=1;i<=n;i++){
for(int j=0;j<cnt;j++){
int &u=g[j].u,&v=g[j].v,&w=g[j].w;
if(dis[u]+w<dis[v]){
if(i==n) return 1;
dis[v]=dis[u]+w;
}
}
}
return 0;
}
Floyd算法
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(a[i][k]&&a[k][j]) a[i][j]=1; //传递闭包
}
}
}
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(a[i][k]+a[k][j]<a[i][j]) a[i][j]=a[i][k]+a[k][j]; //任意两点最短路
}
}
}
Others
- 对于最短路,若有负环存在,则起始点与此环相连的所有点的最短路为无穷小。可通过dfs标记所有无穷小的点。
- 相反对于最长路类似。
- 对于有向图,求其他所有点到1号点的最短路径。即将原图建立反向图,再对1号点求单源最短路。
- 若求一条1~n的路径,使得这条路径中的最小长度的边长度最大,即将求最长路的松弛操作改为
min(dis[u],w)>dis[v]
- 同理,求一条1~n的路径,使得这条路径中的最长的边的长度最小,即将求最短路的松弛操作改为
max(dis[u],w)<dis[v]