1. 程式人生 > >[BZOJ1706][usaco2007 Nov]relays 奶牛接力跑

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

輸出 read 有用 都是 for 跑步 表示 ace cst

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; }

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