zoukankan      html  css  js  c++  java
  • [BZOJ] 1706: [usaco2007 Nov]relays 奶牛接力跑

    1706: [usaco2007 Nov]relays 奶牛接力跑

    Time Limit: 5 Sec  Memory Limit: 64 MB
    Submit: 707  Solved: 367
    [Submit][Status][Discuss]

    Description

    FJ的N(2 <= N <= 1,000,000)头奶牛选择了接力跑作为她们的日常锻炼项目。至于进行接力跑的地点 自然是在牧场中现有的T(2 <= T <= 100)条跑道上。 农场上的跑道有一些交汇点,每条跑道都连结了两个不同的交汇点 I1_i和I2_i(1 <= I1_i <= 1,000; 1 <= I2_i <= 1,000)。每个交汇点都是至少两条跑道的端点。 奶牛们知道每条跑道的长度length_i(1 <= length_i <= 1,000),以及每条跑道连结的交汇点的编号 并且,没有哪两个交汇点由两条不同的跑道直接相连。你可以认为这些交汇点和跑道构成了一张图。 为了完成一场接力跑,所有N头奶牛在跑步开始之前都要站在某个交汇点上(有些交汇点上可能站着不只1头奶牛)。当然,她们的站位要保证她们能够将接力棒顺次传递,并且最后持棒的奶牛要停在预设的终点。 你的任务是,写一个程序,计算在接力跑的起点(S)和终点(E)确定的情况下,奶牛们跑步路径可能的最小总长度。显然,这条路径必须恰好经过N条跑道。

    Input

    * 第1行: 4个用空格隔开的整数:N,T,S,以及E

    * 第2..T+1行: 第i+1为3个以空格隔开的整数:length_i,I1_i,以及I2_i, 描述了第i条跑道。

    Output

    * 第1行: 输出1个正整数,表示起点为S、终点为E,并且恰好经过N条跑道的路 径的最小长度

    Sample Input

    2 6 6 4
    11 4 6
    4 4 8
    8 4 9
    6 6 8
    2 6 9
    3 8 9

    Sample Output

    10

    HINT

     

    Source

    Gold

    Analysis

    分步Floyd qwq

    我今儿算是学到了新套路了...

    首先复习一波Floyd原理

    三层循环 k i j

    表示 i -> j 的路径中插入 k ,如果路径更短的话就更新为 i -> k -> j

    所以根据这个

    我们知道:整个邻接矩阵更新几次,就是所有的最短路径里有几条边

    (如果不更新的话,那么所有路径都只有一条边,也就是初始矩阵)

    那么把这个写成一个矩阵间的二元运算关系,A @ B = C

    在这个过程中,C[ i ][ j ] = min(C[ i ][ j ],A[ i ][ k ]+B[ k ][ j ])

    和Floyd是一样的

    这东西,还符合结合律

    所以对于 k 步Floyd 我们可以写成一个矩阵快速幂,只是运算从矩阵相乘变成了这个单步Floyd

    那么对于这道题

    其实就是求 n 步Floyd之后起点和终点之间的距离

    那么一个离散化(因为数据范围有点诡异)+ 一个分步Floyd求终矩阵

    比较简单,没有其他坑点

    Code

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<algorithm>
      4 using namespace std;
      5 
      6 const int inf = 1e9;
      7 int Poi = 1,poi,Chart[300],chart[3000000],s,t,n,k,a,b,c;
      8 
      9 struct MAT{
     10     int mat[300][300];
     11     MAT(){
     12         for(int i = 1;i < 300;i++)
     13             for(int j = 1;j < 300;j++)
     14                 mat[i][j] = inf;
     15     }
     16     
     17     void print(){cout << endl;
     18         for(int i = 1;i <= n;i++){
     19             for(int j = 1;j <= n;j++)
     20                 cout << mat[i][j] << ' ';
     21             cout << endl;
     22         }
     23     }
     24 }S;
     25 
     26 struct list{
     27     int a,b,c;
     28 }arr[300];
     29 
     30 int find(int x){
     31     int L = 1,R = Poi-1,mid;
     32     while(L < R){
     33         mid = (L+R)/2;
     34         if(Chart[mid] < x) L = mid+1;
     35         else R = mid;
     36     }return L;
     37 }
     38 
     39 void Init(){    
     40     sort(chart,chart+poi);
     41     Chart[Poi++] = chart[0];
     42     Poi = 1;
     43     for(int i = 1;i < poi;i++)
     44         if(chart[i] != Chart[Poi-1]) Chart[Poi++] = chart[i];
     45     s = find(s);
     46     t = find(t);
     47     for(int i = 1;i <= n;i++){
     48         int aa,bb;
     49         aa = find(arr[i].a),bb = find(arr[i].b),c = arr[i].c;
     50 //        printf("%d %d %d
    ",aa,bb,c);
     51         S.mat[aa][bb] = S.mat[bb][aa] = c;
     52     }n = Poi-1;
     53 }
     54 
     55 MAT mul(MAT A,MAT B){
     56     MAT C;
     57     for(int k = 1;k <= n;k++)
     58         for(int i = 1;i <= n;i++)
     59             for(int j = 1;j <= n;j++)
     60                 C.mat[i][j] = min(C.mat[i][j],A.mat[i][k]+B.mat[k][j]);
     61     return C;
     62 }
     63 
     64 MAT ksm(MAT A,int kk){
     65 //    printf("BFYAYIYE");
     66     MAT B = A; kk--;
     67 //    if(!kk) return A; 显然这行代码没有任何问题,但是加入后这个RE了,求大佬解释啊qwq
     68     
     69     
     70     while(kk){
     71 //        B.print();
     72         if(kk&1) B = mul(B,A);
     73         A = mul(A,A);
     74         kk >>= 1;
     75     }return B;
     76 }
     77 
     78 int main(){
     79     freopen("LLQ.in","r",stdin);
     80 //    freopen("LLQ.out","w",stdout);
     81     
     82     scanf("%d%d%d%d",&k,&n,&s,&t);
     83     
     84     for(int i = 1;i <= n;i++){
     85         scanf("%d%d%d",&c,&a,&b);
     86         arr[i].a = a;
     87         arr[i].b = b;
     88         arr[i].c = c;
     89 //        chart[poi++] = a;
     90         chart[poi++] = a;
     91         chart[poi++] = b;
     92     }
     93     
     94     Init();
     95     
     96 //    for(int i = 0;i <= Poi;i++) cout << Chart[i] << ' ';
     97     
     98 //    S.print();
     99     S = ksm(S,k);
    100     
    101     printf("%d",S.mat[s][t]);
    102     
    103     return 0;
    104 }
    分步Floyd
  • 相关阅读:
    团队项目——地铁信息查询数据结构设计
    用Visio画UML顺序图
    用Visio画UML用例图
    结对编程项目进展——第四周
    结对编程项目进展——第三周
    结对项目进展第一周——初步认识结对编程
    个人项目四则运算生成程序进展——第三周
    hbase各种遍历查询shell语句 包含过滤组合条件
    linux c段错误分析方法
    SMB SMB2 协议wiki
  • 原文地址:https://www.cnblogs.com/Chorolop/p/7588973.html
Copyright © 2011-2022 走看看