最后复习之最短路

来源:互联网 发布:怎样查看淘宝消费总额 编辑:程序博客网 时间:2024/05/04 22:20

这里写图片描述
有这么几种最短路算法:floyd、dijkstra、bellman-ford、spfa
一、floyd:
基本过程:枚举中间点,然后枚举起点和终点,用中间点去更新起点到终点的距离。
证明:用每个点去更新所有它能更新的点,是不是就是最短路了?(然而并不会证明)。
多源最短路、求最小环、判断负环、适合稠密图
求最小环:在求最大标号为n的最小环时,预习求出1-n-1的最短路,然后找出两个点i,j,使得i到j的距离(不会经过n,因为只求了1-n-1的最短路)加上i和j到n的距离的和最小,这就是要求的最小环。
判断负环:就是边求边判断,如果存在点到自己的距离小于0,那么就出现了负环。
模板题codevs 1557 热浪
//我的floyd只有70分,不知道floyd能不能ac这个题

for (int k=1;k<=n;k++)    for (int i=1;i<=n;i++)        if (i!=k)            for (int j=1;j<=n;j++)                if (j!=k&&j!=i)                    g[i][j]=min(g[i][j],g[i][k]+g[k]

二、dijkstra:
基本过程:和上一篇的prim差不多,改变就是不再是到最小生成树的距离,而是到起点的距离,即每次找离起点最近的点放入最短路。
证明:对于新加进来的肯定不会有更短的路了,虽然对这个点只有在它之前求出最短路的来更新,但是在这个点之后进来的点一定不能更新这个点到起点的距离。
单源最短路、求最小环、判断负环、适合稠密图、不能处理带有负边权的图
求最小环:不断地删去某条边,求出删去之后这条边起点到终点的最短距离,再加上这条边的长度就是目前求的环的长度,求出最小的就行了。
判断负环:临时想出来的。。如果新进来的可以更新已经求出最短路的点的距离那么就存在负环。

for (int i=1;i<=n;i++)    {        int k=0;        for (int j=1;j<=n;j++)            if (!f[j]&&dis[j]<dis[k])                k=j;        f[k]=1;        for (int j=1;j<=n;j++)            if (!f[j]&&dis[j]>dis[k]+g[k][j])                dis[j]=dis[k]+g[k][j];    }

三、bellman-ford:
基本过程:进行n-1遍对所有边的松弛操作。
证明:每次至少将一条边变成最终松弛状态(就是不会再被用来松弛了)吧,然后图中最长的最短路长度为n-1。
单源最短路、求最小环、判负环、适合稀疏图
求最小环:和dijkstra差不多去删边。
判断负环:在求完最短路之后如果还有边可以松弛,那么就存在负环。

for (int i=1;i<=n-1;i++)    for (int j=1;j<=2*m;j++)    {        a=bian[j].from;b=bian[j].to;        dis[b]=min(dis[b],dis[a]+bian[j].l);    }

四、spfa:
基本过程:通过队列,不断地松弛一些边,因为这些边的终点到起点的距离变小了,那么这些终点连接的其他点也可能可以更新,所以把这些终点们加入队列,只要队列里还有点就要继续进行,直到队列为空方才求出最短路。
证明:只要可能能更新其他点的都进队了,现在队列空了,下面的事情。。。
单源最短路、求最小环、判断负环、适合稀疏图
求最小环:应该还是删边吧,另外附上一句上面求最小环除了floyd我都没有试过(~(≧▽≦)/~啦啦啦)。
判断负环:关于spfa判断负环我只会一个比较水方法,就是如果一个点进队次数超过n次那么就存在负环,至于为什么,我并不知道。

int head=1,tail=1;    memset(dis,127/2,sizeof(dis));    dui[1]=s;f[s]=1;dis[s]=0;    int a,b,len;    while (head<=tail)    {        a=dui[head];        len=bian[a].size();//bian是vector版本的邻接表。        for (int i=0;i<len;i++)        {            b=bian[a][i].to;            if (dis[b]>dis[a]+bian[a][i].l)            {                dis[b]=dis[a]+bian[a][i].l;                if (!f[b])                {                    tail++;                    dui[tail]=b;                    f[b]=1;                }            }        }        head++;        f[a]=0;    }
0 0
原创粉丝点击