图论-最短路个人总结

图论-最短路个人总结

差分约束

如若一个系统由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)\\ BA<=c(1)CB<=a(2)CA<=b(3)
我们要知道 C − A C-A CA的最大值,即 C − A < = T C-A<=T CA<=T T T T的值。通过 ( 1 ) + ( 2 ) (1)+(2) (1)+(2),可以得到 C − A < = a + c C-A<=a+c CA<=a+c,所以这个问题就是求。对于 B − A < = c B-A<=c BA<=c 来说,等价于 B < = c + A B<=c+A B<=c+A,类似于求最短路中的松弛操作if(dis[u]+w,松弛操作的目的就是尽可能使dis[u]+w>=dis[v],所以求 T ​ T​ T的值就是求A~>B,B~>C,A~>C,所形成的有向图中A~>C的最短路径
图论-最短路个人总结_第1张图片
相反的若形如以下:
对 于 形 如 : 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)\\ BA>=c(1)CB>=a(2)CA>=b(3)
并求 C − A C-A CA的最小值,即 C − A > = T C-A>=T CA>=T T T T的值,也就是求上图中C~>A的最长路径。
若有形如 A − B = c A-B=c AB=c的等式,可以转化为 c < = A − B < = c c<=A-B<=c c<=AB<=c,即 A − B < = c , B − A < = − c A-B<=c,B-A<=-c AB<=c,BA<=c
若是整数规划,且有形如 A − B < c A-B<c AB<c,可以转化为 A − B < c − 1 A-B<c-1 AB<c1

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)

你可能感兴趣的:(图论)