【图论】最短路径

最短路径问题(floyed.cpp dijkstra.cpp)

题目描述
平面上有n个点(n<=100),每个点的坐标均在-10000~10000之间。其中的一些点之间有连线。若有连线,则表示可从一个点到达另一个点,即两点间有通路,通路的距离为两点间的直线距离。现在的任务是找出从一点到另一点之间的最短路径。


输入
第1行:1个整数n

第2..n+1行:每行2个整数x和y,描述了一个点的坐标

第n+2行:1个整数m,表示图中连线的数量

接下来有m行,每行2个整数i和j,表示第i个点和第j个点之间有连线

最后1行:2个整数s和t,分别表示源点和目标点

输出
第1行:1个浮点数,表示从s到t的最短路径长度,保留2位小数

样例输入
5
0 0
2 0
2 2
0 2
3 1
5
1 2
1 3
1 4
2 5
3 5
1 5

样例输出
3.41


--------------------------------------------------------------------


我们可以用勾股定理,将每两个点的权值算出来(两点之间没有边的为∞),完成构图。


---------------------------------------------------------------------


求最短路的四种算法(u[i][j]为连接i与j的边的权值, dis[i][j]为从i到j的最短路径长度,dis[i]为从起点至i的最短路径,s为起点,e为终点):

一、Floyd算法

       算法步骤:

                      1、初始化。使dis[i][j] = u[i][j];

                      2、依次枚举中间点k;

                      3、如果dis[i][j] > dis[i][k] + dis[k][j],则将dis[i][j]替换;

                      4、dis[s][e]为最终答案。

       注意:外层循环一定要枚举k。

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

二、Dijkstra算法

      算法步骤:

                      1、初始化。使dis[i] = u[s][i];

                      2、从所有未被访问的节点中选择dis最小的那一个;

                      3、重新计算dis[i]的最短路径长;

                      4、给现在被选中的节点打上标记。

        5、dis[e]为最终答案。


for(int i = 1; i <= n; i++)
{
    int p = 0, j, mins = 1 << 30;
    for(j = 1; j <= n; j++)
    {
        if(!v[j] && dis[j] < mins)
            p = j, mins = dis[j];
    }
    if(!p)
        return 0;
    v[p] = 1;
    for(j = 1; j <= n; j++)
        dis[j] = min(dis[j], dis[p] + u[p][j]);
}


三、Bellman-Ford算法

算法步骤:

1、给每一个点编号;

2、依次每句每一条边,更新dis[i]的最短距离;

3、dis[e]为最终答案。

for(int i = 1; i <= n; i++)
{
    for(int j = 1; j <= E; j++)
        dis[v] = min(dis[v], dis[u] + w[j]); //u和p表示gaibian
}

四、SPFA算法

算法步骤:

1、将目前的点加入队列;

2、取出队首元素;

3、若通过该点可更新另一个点dis[i]的值,则进行4,否则执行3,直到连接该点的所有边枚举完;

4、若该点不在队列中,则将该点加入队列;

5、dis[e]为最后答案。

for(int i = 1; i <= n; i++)
{
    int p = queue.front();
    queue.pop();
    v[p] = 0;
    for(int j = 1; j <= n; j++)
    {
        if(dis[j] > dis[p] + w[p][j])
        {
            dis[j] = dis[p] + w[p][j];
            if(!v[j])
            {
                v[j] = 1;
                queue.push(j);
            }
        }
    }

猜你喜欢

转载自blog.csdn.net/C20181503csy/article/details/52848151