• 洛谷2886 floyd算法+矩阵乘法变形


    题目链接:https://www.luogu.com.cn/problem/P2886

    题目要求求出点(S,T)之间经过k条边的最短路径,而对于长度为x的最短路径矩阵和长度为y的最短路径矩阵,可得到长度为x+y的最短路径矩阵,这可以效仿矩阵乘法进行更新(满足矩阵乘法的性质)。最初的矩阵是点对之间长度为1的最短路径矩阵,可以用归纳法证明A矩阵的k次幂矩阵中(i,j)位置的元素就是点对之间经过k个点的最短路。这其实运用了倍增的思想。比如说需要经过10条边,我们就可以将十变成(1010),此时只要求经过2条边的矩阵和经过8条边的矩阵在做一次矩阵乘法即可。

    有一个注意点是矩阵不能开太大。

    代码如下:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef unsigned int ui;
     4 typedef long long ll;
     5 typedef unsigned long long ull;
     6 #define pf printf
     7 #define mem(a,b) memset(a,b,sizeof(a))
     8 #define prime1 1e9+7
     9 #define prime2 1e9+9
    10 #define pi 3.14159265
    11 #define lson l,mid,rt<<1
    12 #define rson mid+1,r,rt<<1|1
    13 #define scand(x) scanf("%llf",&x) 
    14 #define f(i,a,b) for(int i=a;i<=b;i++)
    15 #define scan(a) scanf("%d",&a)
    16 #define mp(a,b) make_pair((a),(b))
    17 #define P pair<int,int>
    18 #define dbg(args) cout<<#args<<":"<<args<<endl;
    19 #define inf 0x3f3f3f3f
    20 inline int read(){
    21     int ans=0,w=1;
    22     char ch=getchar();
    23     while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
    24     while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
    25     return ans*w;
    26 }
    27 int n,m,t,e;
    28 const int maxn=210;
    29 int Hash[maxn*5];//建立映射表 
    30 int tn;//点的数量 
    31 struct matrix{
    32     int a[maxn][maxn];
    33     matrix operator * (const matrix &x) const
    34     {
    35         matrix c;
    36         memset(c.a,inf,sizeof(c.a));//初始结果是正无穷大矩阵,便于之后更新它 
    37         for(int k=1;k<=tn;k++)
    38             for(int i=1;i<=tn;i++)
    39                 for(int j=1;j<=tn;j++)
    40                 {
    41                     c.a[i][j]=min(c.a[i][j],a[i][k]+x.a[k][j]);//当前矩阵乘以x矩阵之后的结果存放在c矩阵中 
    42                     }    
    43         return c; 
    44     }
    45     matrix()
    46     {
    47         for(int i=0;i<maxn;i++)
    48             for(int j=0;j<maxn;j++)
    49             a[i][j]=0;
    50     }
    51 };
    52 matrix ans,s;
    53 void quick()
    54 {
    55     //s就相当于乘方快速幂中的基数 
    56     ans=s;
    57     n--;
    58     while(n)
    59     {
    60         if(n&1) ans=ans*s;
    61         s=s*s;
    62         n>>=1;
    63     }
    64 }
    65 int main()
    66 {
    67     //freopen("input.txt","r",stdin);
    68     //freopen("output.txt","w",stdout);
    69     std::ios::sync_with_stdio(false);
    70     n=read(),t=read(),m=read(),e=read();
    71     int u,v,w;
    72     memset(s.a,inf,sizeof(s.a));
    73     f(i,1,t)
    74     {
    75         w=read(),u=read(),v=read();
    76         if(!Hash[u])Hash[u]=++tn;//建立映射 
    77         if(!Hash[v])Hash[v]=++tn;
    78         s.a[Hash[u]][Hash[v]]=s.a[Hash[v]][Hash[u]]=w;
    79     }
    80     quick();
    81     pf("%d",ans.a[Hash[m]][Hash[e]]);
    82 } 
  • 相关阅读:
    [转]群控电梯调度算法
    [转] 电梯调度算法总结
    [转]grub2.0和之前版本修复解决方案
    [转]Ubuntu 10.04 编译安装最新版本Linux2.6.34内核
    [转]PS2 键盘工作方式
    [转]个人管理 - 目标管理之前,你会时间管理吗
    [转]ubuntu 下编译内核简单步骤
    [转]关闭Google安全搜索,实现无限制搜索
    [转]Vim 复制粘贴探秘
    [转]Linux文件搜索
  • 原文地址:https://www.cnblogs.com/randy-lo/p/12724584.html
Copyright © 2020-2023  润新知