学习图算法----最短路径问题

来源:互联网 发布:unity3d旧版动画系统 编辑:程序博客网 时间:2024/05/16 06:38

<一>Dijkstra   (无法处理负权边,求单源最短路径)

int lowcost[N]; //存储所求点到各点的最短路径值,这里假定出发点是点1,初始化全部为INF (#define INF  +∞)

int road[N][N]; //存储各点之间的权值.  (若不存在通路,则赋值为INF)

bool isFind[N]; //true表示某点已求得最短路径,初始化为false.

void Dijkstra()

{

    for(int i=2;i<N;i++)         //将原点到各点的最短路径都先赋值为与原点直接的通路值

        lowcost[i]=road[1][i];

    lowcost[1]=0; //点1到自己的最短路径为0;

    isFind[1]=true; //点1已求得最短路径

    for(int i=2;i<N;i++)    //寻找除了原点外的所有点的最短路径,这里是N-2;

    {

        int min=INF;      //初始化为无穷大

        int index=0;

        for(int j=2;j<N;j++)     //找出与原点最近的一个点

        {

            if(!isFind[j] && lowcost[j]<min)

            {

                min=lowcost[j];

                index=j;

            }

        }

        isFind[index]=true;

        for(int j=2;j<N;j++)

        {

             if(!isFind[j] && lowcost[j]>min + road[index][j])  //松弛,既若找到的那个最近的点与其他点的距离之和小于原点与相应点的距离,则覆盖之。

             {

                  lowcost[j]=min + road[index][j];

             }

         }

    }

}

<二>Floyd  (求各点作为源点的最短路径)

int road[N][N]; //存储各点之间的权值

int lowcost[N][N]; //存储所有点的各自对应的最短路径

void Floyd()

{

    //首先初始化road[N][N]和lowcost[N][N]中的各值为无穷大,这里省去。

    //根据题目给出的各路权值刷新road[N][N]中的相应值

    for(int i=1;i<N;i++)          //刷新lowcost里的相应值

        for(int j=1;j<N;j++)

            lowcost[i][j]=road[i][j];

    for(int i=1;i<N;i++)

        for(int j=1;j<N;j++)

            for(int k=1;k<N;k++)

                if(lowcost[j][k]>lowcost[j][i]+lowcost[i][k]) //松弛

                    lowcost[j][k]=lowcost[j][i]+lowcost[i][k];

}

<三>SPFA (Shortest Path Faster Algorithm,不可以处理负权边,但是可以判断是否存在负权边)

queue<int> Q;

bool inQueue[N]; //判断某点是否在队列里,初始化为false

int road[N][N]; //存储各点间的权值,初始化为无穷大

int lowcost[N];  //存储源点到各点的最短路径,初始化为无穷大

int count[N];   //统计某点进入队列的次数,初始化为0

void SPFA()            //假设源点为1

{

    bool isNegative=false;

    lowcost[1]=0;  //源点到自己的距离为0

    Q.push(1);   //将源点入队

    inQueue[1]=true;   //标记源点已在队内

    while(!Q.empty())

    {

        int temp=Q.front();

        Q.pop();

        count[temp]++;

        if(count[temp]>N)  //当某点入队次数大于N时,说明存在负权边,求不到最短路径

        {

            isNegative=true;

            break;

        }

        inQueue[temp]=false;

        for(int i=1;i<N;i++)

        {

            if(lowcost[i]>lowcost[temp]+road[temp][i]) //松弛

           {

                lowcost[i]=lowcost[temp]+road[temp][i];

                if(inQueue[i]==false)

               {

                    Q.push(i);

                    inQueue[i]=true;

                    count[i]++;

               }

           }

       }

   }