[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\n", ans.num[S][E]);
    return 0;
}

 

posted @ 2017-09-25 19:25  jzyy  阅读(183)  评论(0编辑  收藏  举报