• [BZOJ1706][usaco2007 Nov]relays 奶牛接力跑


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

    Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 708  Solved: 368 [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
     
    题意为图上从$S$到$E$走$N$条路径,路径上的最小边权为多少
    可以发现,把矩阵乘法的$sum$改成取$min$一样满足分配律
    求把图的邻接矩阵的$N$次方即可
    但是矩阵规模太大要TLE,可以发现只有很少的边,只有边两端的点有用,离散化一下即可
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    char buf[10000000], *ptr = buf - 1;
    inline int readint(){
        int f = 1, n = 0;
        char ch = *++ptr;
        while(ch < '0' || ch > '9'){
            if(ch == '-') f = -1;
            ch = *++ptr;
        }
        while(ch <= '9' && ch >= '0'){
            n = (n << 1) + (n << 3) + ch - '0';
            ch = *++ptr;
        }
        return f * n;
    }
    const int maxn = 1000 + 10;
    struct Matrix{
        int n, m, num[110][110];
        Matrix(){}
        Matrix(int _n, int _m){
            n = _n;
            m = _m;
            memset(num, 0x3f, sizeof(num));
        }
        Matrix operator * (const Matrix &a){
            Matrix b(n, a.m);
            for(int i = 1; i <= n; i++)
                for(int j = 1; j <= b.m; j++)
                    for(int k = 1; k <= m; k++)
                        b.num[i][j] = min(b.num[i][j], num[i][k] + a.num[k][j]);
            return b;
        }
    };
    Matrix ksm(Matrix a, int b){
        Matrix s = a;
        b--;
        while(b){
            if(b & 1) s = s * a;
            b >>= 1;
            a = a * a;
        }
        return s;
    }
    int N, T, S, E;
    int w[maxn], u[maxn], v[maxn];
    int num[maxn * 2], cnt = 0;
    int main(){
        fread(buf, sizeof(char), sizeof(buf), stdin);
        N = readint();
        T = readint();
        S = readint();
        E = readint();    
        num[++cnt] = S;
        num[++cnt] = E;
        for(int i = 1; i <= T; i++){
            w[i] = readint();
            num[++cnt] = u[i] = readint();
            num[++cnt] = v[i] = readint();
        }
        sort(num + 1, num + cnt + 1);
        cnt = unique(num + 1, num + cnt + 1) - (num + 1);
        S = lower_bound(num + 1, num + cnt + 1, S) - num;
        E = lower_bound(num + 1, num + cnt + 1, E) - num;
        for(int i = 1; i <= T; i++){
            u[i] = lower_bound(num + 1, num + cnt + 1, u[i]) - num;
            v[i] = lower_bound(num + 1, num + cnt + 1, v[i]) - num;
        }
        Matrix ans(cnt, cnt);
        for(int i = 1; i <= T; i++) ans.num[u[i]][v[i]] = ans.num[v[i]][u[i]] = w[i];
        ans = ksm(ans, N);
        printf("%d
    ", ans.num[S][E]);
        return 0;
    }
  • 相关阅读:
    PHP与CI学习笔记
    The Sum of the k-th Powers(Educational Codeforces Round 7F+拉格朗日插值法)
    Nastya Hasn't Written a Legend(Codeforces Round #546 (Div. 2)E+线段树)
    Please, another Queries on Array?(Codeforces Round #538 (Div. 2)F+线段树+欧拉函数+bitset)
    Gorgeous Sequence(HDU5360+线段树)
    Subsequence(HDU3530+单调队列)
    Qualification Rounds(Codeforces Round #438 by Sberbank and Barcelona Bootcamp (Div. 1 + Div. 2 combined)+状态压缩)
    Xenia and Weights(Codeforces Round #197 (Div. 2)+DP)
    字节跳动-文远知行杯”广东工业大学第十四届程序设计竞赛
    线段树优化建边
  • 原文地址:https://www.cnblogs.com/ruoruoruo/p/7593503.html
Copyright © 2020-2023  润新知