zoukankan      html  css  js  c++  java
  • 洛谷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
  • 相关阅读:
    Python Module_Socket_网络编程
    Python Module_Socket_网络编程
    从 2017 OpenStack Days China 看国内云计算的发展现状
    从 2017 OpenStack Days China 看国内云计算的发展现状
    说说excel
    一种防脱裤撞库的可能性?
    黑白相片变彩色相片的一种可能性?
    为什么需求文档一定要电子化?
    一个网页布局练习
    css田字格布局
  • 原文地址:https://www.cnblogs.com/li-jia-hao/p/12794491.html
Copyright © 2011-2022 走看看