最短路的一些理解

dij是单源的,只是从一个顶点出发到其它点的最短距离,并且它的全值都是正的,不能够有负值;

Bellman-ford 也是单源的,但是他能够完成负权值的图,这是dij无法达到的,并且能够判断是否存在负环,经过修改可以求最长路;
SPFA是在Bellman-ford上优化的,所以跟快;

floyd算法可以求出任意两点的最短路,索然dij对每个点一次for也能求出,但是复杂度O(n^3)或O(n^2+ne),一次floyd也是O(n^3),
但是floyd更加易懂,简洁;floyd允许带负值的边,但不能有回路(环);floyd很灵活,可以多种变换;

(个人的理解 不是很深,只懂一点)

  1 poj3268

  2 很多牛,要到x这个点,来回多少时间;

  3 正向,反向2次SPFA,2个值相加,然后取最大;

  4 #include<STDIO.H>

  5 #include<string.h>

  6 #include<queue>

  7 #define INF 999999999

  8 using namespace std;

  9 struct node

 10 {

 11     int v;

 12     int val;

 13     int next;

 14 }edge1[100003],edge2[100003];

 15 int head1[1003],dis1[1003],head2[1003],dis2[1003];

 16 int n,m,t,index1,index2;

 17 void add1(int x,int y,int z)

 18 {

 19     int i,j;

 20     edge1[index1].v=y;

 21     edge1[index1].val=z;

 22     edge1[index1].next=head1[x];

 23     head1[x]=index1++;

 24 }

 25 void add2(int x,int y,int z)

 26 {

 27     int i,j;

 28     edge2[index2].v=y;

 29     edge2[index2].val=z;

 30     edge2[index2].next=head2[x];

 31     head2[x]=index2++;

 32 }

 33 void SPFA1(int u)

 34 {

 35     int vis[1003],i,j;

 36     memset(vis,0,sizeof(vis));

 37     queue<int>q;

 38     for(i=1;i<=n;i++)

 39         dis1[i]=INF;

 40     dis1[u]=0;

 41     vis[u]=1;

 42     q.push(u);

 43     while(!q.empty())

 44     {

 45         int v=q.front();

 46         q.pop();

 47         vis[v]=0;

 48         for(i=head1[v];i!=-1;i=edge1[i].next)

 49         {

 50             int tmp=edge1[i].v;

 51             if(dis1[tmp]>dis1[v]+edge1[i].val)

 52             {

 53                 dis1[tmp]=dis1[v]+edge1[i].val;

 54                 if(!vis[tmp])

 55                 {

 56                     q.push(tmp);

 57                     vis[tmp]=1;

 58                 }

 59             }

 60         }

 61     }

 62 }

 63 void SPFA2(int u)

 64 {

 65     int vis[1003],i,j;

 66     memset(vis,0,sizeof(vis));

 67     queue<int>q;

 68     for(i=1;i<=n;i++)

 69         dis2[i]=INF;

 70     dis2[u]=0;

 71     vis[u]=1;

 72     q.push(u);

 73     while(!q.empty())

 74     {

 75         int v=q.front();

 76         q.pop();

 77         vis[v]=0;

 78         for(i=head2[v];i!=-1;i=edge2[i].next)

 79         {

 80             int tmp=edge2[i].v;

 81             if(dis2[tmp]>dis2[v]+edge2[i].val)

 82             {

 83                 dis2[tmp]=dis2[v]+edge2[i].val;

 84                 if(!vis[tmp])

 85                 {

 86                     q.push(tmp);

 87                     vis[tmp]=1;

 88                 }

 89             }

 90         }

 91     }

 92 }

 93 int main()

 94 {

 95     int i,j;

 96     while(scanf("%d%d%d",&n,&m,&t)!=EOF)

 97     {

 98         index1=index2=1;

 99         memset(dis1,0,sizeof(dis1));

100         memset(head1,-1,sizeof(head1));

101         memset(dis2,0,sizeof(dis2));

102         memset(head2,-1,sizeof(head2));

103         for(i=0;i<m;i++)

104         {

105             int x,y,z;

106             scanf("%d%d%d",&x,&y,&z);

107             add1(x,y,z);

108             add2(y,x,z);

109         }

110 

111         SPFA1(t);

112 

113         /*for(i=1;i<=n;i++)

114         printf("%d ",dis1[i]);

115         printf("\n");*/

116 

117         SPFA2(t);

118 

119         /*for(i=1;i<=n;i++)

120         printf("%d ",dis2[i]);printf("\n");*/

121 

122         int max=0;

123         for(i=1;i<=n;i++)

124         {

125             if(max<dis2[i]+dis1[i])

126                 max=dis2[i]+dis1[i];

127         }

128         printf("%d\n",max);

129     }

130 }

 

/*poj2570

floyd算法来找到所有可能的路径;

用二进制26位表示路径;

0000000000.......111,这个表示abc;

floyd时 map[i][j]|=map[i][k]&map[k][j];

|表示有新的路径 那么就合并路径,&表示存在这个路;

最后遍历26个字母即可;*/

//poj2570

#include<stdio.h>

#include<string.h>

int map[203][203];

int n;

int main()

{

    int i,j,l,x,y;

    while(scanf("%d",&n)!=EOF)

    {

        if(!n)break;

        memset(map,0,sizeof(map));

        char s[50];

        while(1)

        {

            x,y;

            scanf("%d %d",&x,&y);

            if(x==0&&y==0)

                break;

            scanf("%s",s);

            l=strlen(s);

            for(i=0;i<l;i++)

            {

                map[x][y]|=1<<(s[i]-'a');

            }

        }

        //floyd

        for(i=1;i<=n;i++)

            for(j=1;j<=n;j++)

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

                {

                    map[j][k]|=(map[j][i] & map[i][k]);

                }

        char ii;

        while(1)

        {

            scanf("%d %d",&x,&y);

            if(x==0&&y==0)break;

            for(ii='a';ii<='z';ii++)

            {

                if(map[x][y] & (1<<(ii-'a')))

                {

                    printf("%c",ii);

                }

                

            }

            if(!map[x][y])

            {

                printf("-");

            }

            putchar('\n');

        }

        putchar('\n');

    }

}







//poj2263

/*floyd来求解最大能够载重;

应为A->C可以有2种情况 A->B,B->C或者A->C,要得到A->C这条道路最大的载重量,由于A,B,C这三条路的载重不同,

所以要找出A->B,B->C的最小载重,因为如果取大的,另外一条就不能了,然后再取直接到和间接到的最大值,

此时可以用floyd来解决问题;*/

#include<stdio.h>

#include<string.h>

#define INF 99999999

int map[205][205];

int num;//统计city

int n,m;

char s[20],e[20];

char in1[30],in2[30];

char city[205][50];

int max(int x,int y)

{

    return x>y?x:y;

}

int min(int x,int y)

{

    return x<y?x:y;

}

int inset(char a[])

{

    int i,j;

    for(i=0;i<num;i++)

    {

        if(strcmp(city[i],a)==0)

        {

            return i;

        }

    }

    num++;

    strcpy(city[i],a);

    return i;

}

int floyd()

{

    int i,j,k;

    for(i=0;i<n;i++)

        for(j=0;j<n;j++)

            for(k=0;k<n;k++)

            {

                map[j][k]=max(map[j][k],min(map[j][i],map[i][k]));

            }

    int x,y;

    x=inset(s);

    y=inset(e);

    return map[x][y];

}

int main()

{

    int i,j;

    int ff=0;

    while(scanf("%d%d",&n,&m)!=EOF)

    {

        if(!n&&!m)break;

        memset(map,0,sizeof(map));

        num=0;

        for(i=0;i<=n;i++)

            map[i][i]=INF;

        for(i=0;i<m;i++)

        {

            int z;

            scanf("%s %s %d",in1,in2,&z);

            int x,y;

            x=inset(in1);

            y=inset(in2);

            map[x][y]=map[y][x]=z;

        }

        scanf("%s %s",s,e);

        int ans=floyd();

        printf("Scenario #%d\n",++ff);

        printf("%d tons\n",ans);

        printf("\n");

    }

}

 

你可能感兴趣的:(最短路)