最短路的一些理解

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");
    }
}
时间: 2024-11-05 20:41:19

最短路的一些理解的相关文章

POJ 3169.Layout 最短路

Layout Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11612   Accepted: 5550 Description Like everyone else, cows like to stand close to their friends when queuing for feed. FJ has N (2 <= N <= 1,000) cows numbered 1..N standing along

【刷题】 [SDOI2010]魔法猪学院/luoguP2483_k短路_可持久化可并堆(并没有)

题面 LuoguP2483 大意:给一张\(n\)个点,\(m\)条边的有向图,保证能从\(1\)号点到\(n\)号点,边有正实数边权\(e_i\),路径权值为边权和.问从\(1\)号点到\(n\)号点最多能选多少条本质不同的路径,使得这些路径权值和不超过给定的\(E\)? \(2\leq n\leq 5000,1\leq m\leq 200000,1\leq e_i,E\leq 10^7\) 题解 这是一道k短路裸题.因为你肯定要选前k短的.而且求k短路是一条条求出来的. 接下来的问题就是怎么

D11

=-=感觉今天的题目好难... 主要是没有碰到过,所以会觉得不懂怎么写.. 其实现在想想,T1,T2,T3其实都好水..T1其实没有做过还真不会,有做过的话就是个大水题了 T2找最小环..超级裸的,但是自己不会打=-= T3直接FLOYD...+判断障碍物是否有在同一条线上 今天按理来说只有T4会比较难一些..DP+贪心 T1:模拟+数学思想 #include<cstdio> #include<cstring> #include<algorithm> using nam

&lt;学习笔记&gt; 查分约束系统

定义:如果一个系统由n个变量和m个约束条件组成,形成m个形如 ai - aj ≤ k 的不等式(i,j∈[1,n],k为常数),则称其为差分约束系统(system of difference constraints).亦即,差分约束系统是求解关于一组变量的特殊不等式组的方法. 栗子:给出这样的一组不等式 A-B < = 3 B-C < = 6 C-D < = 5 E-C < = 2 B-E < = 3 求A-D的最大值. 经过一番脑跑之后,得出答案13.但是我们不能总是脑跑啊

shell编程基础干货

变量及赋值 设置变量   A=‘china’  取消变量  unset  A    加上 export 关键字  代表全局变量 a=$(ls -l /root/bin)   ##运行里面的命令,并把结果返回给变量 a 特殊变量\ $$ 表示当前进程编号 $0 表示当前脚本名称 $n 表示 n 位置的输入参数( n 代表数字, n>=1) $# 表示参数的个数,常用于循环  $* 表示所有参数列表     “ $* “   加双引号时循环参数时不换行输出  echo命令   echo $A   

POJ 1847 Tram 【最短路,spfa算法,题意理解是关键呀!!】

Tram Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 13468   Accepted: 4954 Description Tram network in Zagreb consists of a number of intersections and rails connecting some of them. In every intersection there is a switch pointing to t

最短路:我的理解--Dijkstra算法

最短路径:Dijkstra算法 用来计算从一个点到其他所有点的最短路径的算法,是一种单源最短路径算法.也就是说,只能计算起点只有一个的情况. Dijkstra的时间复杂度是O (N2),它不能处理存在负边权的情况. 算法描述:        设起点为s,dis[v]表示从s到v的最短路径,pre[v]为v的前驱节点,用来输出路径.        a)初始化:dis[v]=∞(v≠s); dis[s]=0; pre[s]=0;        b)For (i = 1; i <= n-1 ; i++

对最短路的理解

最短路问题是一种常见的问题,她一般被描述为包含n个点和m,主要分为两类:(1)(单源最短路径)求解从起点s到终点e的最短路径(2)(多源最短路径)求解图中任意两点的最短路径. 常用的解题算法有四种:Dijkstra,bellman-ford,spfa,Floyd

UESTC30-最短路-Floyd最短路、spfa+链式前向星建图

最短路 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的T-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗? Input 输入包括多组数据. 每组数据第一行是两个整数NN ,MM (N≤100N≤100 ,M≤10000M≤1000