• 洛谷P2886 [USACO07NOV]Cow Relays G


     题意:给定一个无向图,和两个点,求出给定两点间经过n条路的最短路。

    思路分析:其实刚开始看题时想到的是dijisktla,但后来由于想不出来输出规定边数的最短路长度的方法,就放弃了。

    这道题用到的是floyd,反正T<=100,我们可以准备两个数组,其中一个始终装着每个边的初始情况,这样我们每将两个矩阵计算一次,给定两点间经过的边数就会增加一次,故我们只需跑n-1次即可,这样我们就能坐等AC超时了,由于n<= 1,000,000,硬算是一定会超时的,于是我们还需要其他的优化方法。我们看着Floyd,想起来什么没有?对了,就是矩阵乘法,我们可以运用二进制拆分的方法,将n-1拆成若干个二进制位,修改原数组,再进行运算,就没有问题了。

    另外,看见网上的大佬们都用到了离散化,这里我就学了一下。

    代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=1e6+10;
     6 int n,t,s,e,sum,num[N];//num,sum用于离散化 
     7 struct squ{
     8     int a[510][510];
     9     squ operator * (const squ &x)const{  //重载运算符,方便快速幂 
    10         squ c;
    11         memset(c.a,0x3f3f3f3f,sizeof(c.a)); //不能互达的边初始化为无穷 
    12         for(int k=1;k<=sum;++k)
    13         for(int i=1;i<=sum;++i)
    14         for(int j=1;j<=sum;++j)
    15             c.a[i][j]=min(c.a[i][j],a[i][k]+x.a[k][j]);
    16         return c;
    17     }
    18 }dis,ans;
    19 int main(){
    20     memset(dis.a,0x3f3f3f3f,sizeof(dis.a));
    21     scanf("%d%d%d%d",&n,&t,&s,&e);
    22     for(int i=1;i<=t;++i){
    23         int x,y,z;
    24         scanf("%d%d%d",&x,&y,&z);
    25         if(!num[y]) num[y]=++sum;  //离散化 
    26         if(!num[z]) num[z]=++sum;
    27         dis.a[num[y]][num[z]]=dis.a[num[z]][num[y]]=x;
    28     }
    29     n--;
    30     ans=dis;
    31     while(n){
    32         if(n&1) ans=ans*dis;
    33         dis=dis*dis;  //二进制拆分,倍增 
    34         n>>=1;
    35     }
    36     printf("%d
    ",ans.a[num[s]][num[e]]);
    37     return 0;
    38 }
    View Code
  • 相关阅读:
    二维数组中的查找
    浅析Java的Object类
    Alan Turing的纪录片观后感
    近期学习docker遇到的一些问题
    eclipse(STS)安装jd-eclipse插件实现查看API源代码功能
    deepin配置Oracle JDK
    两个有序链表的合并
    Maven 项目中各包单独打成jar包
    一次性密码 && 身份认证三要素
    HTTPS工作流程
  • 原文地址:https://www.cnblogs.com/li-jia-hao/p/12794491.html
Copyright © 2020-2023  润新知