dj的邻接矩阵实现

来源:互联网 发布:ubuntu repair grub 编辑:程序博客网 时间:2024/06/08 00:11
#include <bits/stdc++.h>using namespace std;const int maxn=100,bignum=100001;int g[maxn][maxn],dis[maxn],t[maxn],siz;bool state[maxn];void creat(int k){    memset(g,0,sizeof(g));    for(int i=0;i<=siz;i++)    {        for(int j=0;j<=siz;j++)        {            cin>>g[i][j];        }    }    for(int i=0;i<=siz;i++)    {        dis[i]=g[k][i];    }    memset(state,true,sizeof(state));    state[k]=false;    memset(t,0,sizeof(t));    t[k]=-1;}void addnode(int k){    siz++;    int cur;    for(int i=0;i<=siz;i++)    {        cin>>cur;        g[siz][i]=cur;        g[i][siz]=cur;    }    dis[siz]=g[k][siz];}int findminandstate(){    int minpos,minsum=bignum;    for(int i=0;i<=siz;i++)    {        if(state[i]==true)        {            if(dis[i]<minsum)            {                minpos=i;                minsum=dis[i];            }        }    }    return minpos;}void dj(int k){    int lastpos=k;    for(int j=0;j<=siz;j++)    {        if(j==k)continue;        int minpos=findminandstate();        for(int i=0;i<=siz;i++)        {            if(state[i]&&((g[minpos][i]+dis[minpos])<dis[i]))            {                state[minpos]=false;                dis[i]=g[minpos][i]+dis[minpos];                t[i]=minpos;            }        }    }}int main(){    int k;    cin>>siz>>k;    siz--;k--;    creat(k);    addnode(k);    dj(k);     for(int i=0;i<=siz;i++)cout<<t[i]+1<<" ";     cout<<endl;     for(int i=0;i<=siz;i++)cout<<dis[i]<<" ";    return 0;}void prtg(){    for(int i=0;i<=siz;i++)    {        for(int j=0;j<=siz;j++)        {            cout<<g[i][j]<<" ";        }        cout<<endl;    }}/*6 10 50 100000 40 25 1050 0 15 20 100000 25100000 15 0 10 20 10000040 20 10 0 10 2525 100000 20 10 0 5510 25 100000 25 55 05 10 50 100000 40 2550 0 15 20 100000100000 15 0 10 2040 20 10 0 1025 100000 20 10 010 25 100000 25 55 0*/

maxn:可放的最大节点数,因为以邻接矩阵存储所以开一个较小的数

              Bignum:代码中用的大数,防止int溢出设一个不大不小的100001

              g:邻接矩阵,存放输入数据

              dis:存储节点到根节点距离的数组

              t:存储最小生成树

              siz:存储输入的邻接矩阵大小

              state;存储某个节点是否已挂上生成树,真表示未挂上

creat():一次性读入某个邻接矩阵

addnode():增加节点,需要在调用dj之前使用,不知道能有什么卵用

findminandstate():中间函数,用来找没挂上生成树的离源最近节点

dj():dj]



大概回忆一下dj的思路

目的:求一个边带权有向图中单源的最小生成树

思路的第一步:对于图中一个节点vi,它所邻接到的所有点中,把邻接边权值最小的那个点记作vk,则e=vi-vk一定是最小生成树上的一条边

                          呃这么写以后肯定看不懂再见,那就通俗的来说,想从甲地到乙地,我们有一条路直接从甲到乙,我们还有很多条别的路能直接到不知道什么鬼的地方。而这条直接从甲到乙的路比别的路的<甲地到第一个下车口的距离>还要短,那么显然,不走从甲到乙的这条直接的路的都在绕弯子

    这个第一步的用处在于:每一次从图上选择一个据起点最近的点,从起点到它的那条路肯定是在所需的树上的。

   那么为了能一步步走下去,我们需要一个数组,保存目前从起点到每一个节点的距离。目前没有发现有路的,就记作无限远。

  还有一个就是,每一次确定了一个点后,需要记录下这个确定的状态,以后找点的时候就可以忽略这个点了,同样用一个数组来存。

  这样一来就可以如此描述:

             起始步:将所有起点邻接到的节点,将这个边的长度作为目前起点到这个点的距离记录到数组里。

            循环步:对目前距起点最近且未挂上树的节点,挂上树,并且对这个节点邻接到的所有点便利一次,若<这个点到某个点的边权值>+<起点到这个点的距离>小于<此处的<某个点>到起点的距离>,那么就把<此处的<某个点>到起点的距离>更新为<这个点到某个点的边权值>+<起点到这个点的距离>

循环终止条件:所有节点都挂上树了


原创粉丝点击