2017暑假训练第五天

  今天的训练成功由题目把四种求最短路径的方法都复习了一遍,也算是路遇难题,各显神通吧。

  下面总结一下其中的三种算法(spfa算法是第三种算法的优化,所以只总结第1,2,4这三种算法):

  对于Floyed算法:

  算法的形式就比较暴力,三重循环过滤中间点对每个a[i][j]的缩短作用,过滤完之后结果就是最短路径,而且可以处理负权,易错点就是第一重循环的作用一定要注意。 

  算法的代码如下:

      for (k=1;k<=n;k++){//第一重循环为中间点
        for (i=1;i<=n;i++){
           for (j=1;j<=n;j++){
               if (a[i][j]>a[i][k]+a[k][j]){
                   a[i][j]=a[i][k]+a[k][j];
                 }
             }
          }
     }

  对于Dijkstra算法:

  算法可处理单源头的最短路径问题,简而言之就是找点更新,每次找与源头点的最近的未访问过的点,用这个点的距离去更新余下未访问的点,重复n-1次,得到的dis数组之中存的便是源头到该点的最短距离。

  算法的代码如下:

  int Dijkstra(){
    int i,j,k,l;
    int xx;
    value=1061109567;
    memset (dis,0x3f,sizeof(dis));
    memset (visit,0,sizeof(visit));
    dis[1]=0;
    for (i=1;i<=n-1;i++){
        xx=1061109567;
        place=0;
        for (j=1;j<=n;j++){
            if (!visit[j]&&dis[j]<xx&&dw1[j]){
                place=j;
                xx=dis[j];
            }
        }
        if (place){
            visit[place]=1;
            for (j=1;j<=n;j++){
                if (!visit[j]&&dis[j]>dis[place]+a[place][j]&&dw1[j]){
                    dis[j]=dis[place]+a[place][j];
                }
            }
        }
    }
    for (i=1;i<=n;i++) {value=min(value,dis[i]+p[i]);}
    return value;
  }

  而对于spfa算法:

  算法也是可以处理单源头问题,算法的思路就是反复更新,每次找到路径缩小的点入队,然后用他更新余下他能到达的点,也是在dis数组中存放距离,也可以用于判断是否出现负权回路。

  算法代码如下:

  void spfa(){
    int i,j,k,l;
    int u,v;
    queue<int>qq;
    qq.push(1);
    s[1]=0;
    visit[1]=1;
    total[1]++;
    while (!qq.empty()){
        u=qq.front();
        qq.pop();
        visit[u]=0;
        for (i=head[u];i!=-1;i=p[i].pre){
            v=p[i].to;
            if (s[v]>p[i].val+s[u]){
                s[v]=p[i].val+s[u];
                if (!visit[v]){
                    qq.push(v);
                    visit[v]=1;
                    total[v]++;
                    if (total[v]>=n){
                        cout<<"YES"<<endl;
                        return ;
                    }
                }
            }
        }
    }
    cout<<"NO"<<endl;
}

知识点差不多已经通了一遍,明天的训练以刷体和看博客为主。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值