最短路的一些理解

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("
");*/
116 
117         SPFA2(t);
118 
119         /*for(i=1;i<=n;i++)
120         printf("%d ",dis2[i]);printf("
");*/
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
",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('
');
        }
        putchar('
');
    }
}



//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
",++ff);
        printf("%d tons
",ans);
        printf("
");
    }
}
原文地址:https://www.cnblogs.com/sweat123/p/4502992.html