• poj 3613


    题意:

    求从一个点s 到 一点 e 经过 n 条边的最短路经是多少(可以有重边)

    贴一个floyd算法讲解:

    http://blog.csdn.net/niushuai666/article/details/6772706

    以前一直没仔细想过floyd算法,觉得很简单,今天做这题的时候,看网上的报告都有一句:floyd是每次使用一个中间点k去更新i,j之间的距离,那么更新成功表示i,j之间恰有一个点k时的最短路,如果做N - 1次floyd那么不就是i,j之间借助N - 1 个点时的最短路了。看了很久不明白为什么。也对floyd的最外围的那个k<n产生了疑惑。后来突然想到了,floyd每次更新的都是本身,假如k=3时,dis[1][5]借助dis[1][3]和dis[3][5]成为最短路。不需要去知道1,3之间有多少个点,因为前面已经求出,,(dp?)只知道这一次求出的dis[1][5]多加了一个3这个点。

    回到这题,floyd算法是对自身矩阵更新,而这道题却是更新到另一个矩阵上,所以不会出现刚更新过的值又来更新。。例如下面代码的b.mat[1][3] c.mat[3][5]就分别代表上面的dis[1][3],dis[3][5].我们不需要知道tmp.mat[1][5]已经有的点个数。(即已经更新的次数。)只知道,这次更新会加入一个3到他们中间。所以更新k-1次就行。

     1 void floyd(Mat b,Mat c)
     2 {
     3     tmp.init();
     4     for(int k=1;k<=cnt;k++)
     5         for(int i=1;i<=cnt;i++)
     6             for(int j=1;j<=cnt;j++)
     7             {    
     8                 if(b.mat[i][k] <0 || c.mat[k][j] <0)
     9                     continue;
    10                 if(tmp.mat[i][j]<0 || tmp.mat[i][j] > b.mat[i][k] + c.mat[k][j]  )
    11                      tmp.mat[i][j] = b.mat[i][k] + c.mat[k][j];
    12             }
    13 }

    注意的地方:

    1、N次floyd可以用倍增思想加速,就是自底向上的二分。类似求矩阵快速幂(M67大牛)。

    2、这里还有一点要注意,T的范围是(2~100),所以最多顶点只有200,而顶点标号的范围却(1 ≤ I1i ≤ 1,000; 1 ≤ I2i ≤ 1,000)。这样我们可以将编号离散化。

    3、最后一点这个题的inf要开很大。开始开的是0x5fffffff还是wa了。后来看了某个博客 可以把inf定义为-1。就没这个问题了。值得学习。

    ps:这道题还是有点似懂非懂.....

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 
     6 using namespace std;
     7 
     8 #define maxn 205
     9 
    10 int n,t,st,en;
    11 struct Mat
    12 {  
    13     int mat[maxn][maxn];  
    14     void init()
    15     {
    16         memset(mat,-1,sizeof(mat));
    17     }
    18 };  
    19 
    20 int v[1005];//离散化用
    21 Mat ans,tmp,map;
    22 int cnt;//顶点个数
    23 void init()
    24 {
    25     int val,s,e;
    26     memset(v,0,sizeof(v));
    27     cnt=0;
    28     ans.init();
    29     tmp.init();
    30     map.init();
    31     for(int i=0;i<maxn;i++)
    32         ans.mat[i][i]=0;
    33     for(int i=0;i<t;i++)
    34     {
    35         scanf("%d%d%d",&val,&s,&e);
    36         if(v[s]==0)
    37         {
    38             ++cnt;
    39             v[s]=cnt;
    40         }
    41         if(v[e]==0)
    42         {
    43             ++cnt;
    44             v[e]=cnt;
    45         }
    46         if(map.mat[v[s]][v[e]]<0 || map.mat[v[s]][v[e]] > val)
    47             map.mat[v[s]][v[e]]=map.mat[v[e]][v[s]]=val;
    48     }
    49 }
    50 
    51 void floyd(Mat b,Mat c)
    52 {
    53     tmp.init();
    54     for(int k=1;k<=cnt;k++)
    55         for(int i=1;i<=cnt;i++)
    56             for(int j=1;j<=cnt;j++)
    57             {    
    58                 if(b.mat[i][k] <0 || c.mat[k][j] <0)//意味着是inf
    59                     continue;
    60                 if(tmp.mat[i][j]<0 || tmp.mat[i][j] > b.mat[i][k] + c.mat[k][j]  )
    61                      tmp.mat[i][j] = b.mat[i][k] + c.mat[k][j];
    62             }
    63 }
    64 
    65 Mat copy()
    66 {
    67     Mat a;
    68     for(int i=0;i<=cnt;i++)
    69         for(int j=0;j<=cnt;j++)
    70             a.mat[i][j]=tmp.mat[i][j];
    71     return a;
    72 }
    73 
    74 void solve()
    75 {
    76     while(n)//虽然这里是n,像是更新了n次。但是下面80行那里第一次调用的时候其实并未更新。只是把map,传递给tmp再转给ans.
    77     {
    78         if(n&1)
    79         {
    80             floyd(ans,map);
    81             ans=copy();
    82         }
    83         floyd(map,map);
    84         map=copy();
    85         n>>=1;
    86     }
    87 }
    88 
    89 int main()
    90 {
    91     while(scanf("%d%d%d%d",&n,&t,&st,&en) != EOF)
    92     {
    93         init();
    94         solve();
    95         printf("%d\n",ans.mat[v[st]][v[en]]);
    96     }
    97     return 0;
    98 }

     

     

     

  • 相关阅读:
    Vue+element tree使用,当弹窗关闭时,this.$refs.tree.setCheckedKeys([])不能清空选中
    npm ERR! A complete log of this run can be found in
    Vue面试题之vue实现MVVM数据绑定
    渐变色的ie兼容
    安徽地图
    数组去重的四种方法
    EF Code First创建数据库
    Code First Migrations更新数据库结构(数据迁移)
    Bootstrap 样式大全
    C#程序中:如何向记事本中写入内容和导出内容
  • 原文地址:https://www.cnblogs.com/Missa/p/2669746.html
Copyright © 2020-2023  润新知