POJ 3613 Cow Relays【k边最短路】
题目链接:http://poj.org/problem?id=3613
题目大意:
给出n头牛,t条有向边,起点以及终点,限制每头牛放在一个点上,(一个点上可以放多头牛),从起点开始进行接力跑到终点,求该过程的最小路程。
题解思路:
1.典型的k边最短路,经过且仅经过k条边的最短距离。
2.Floyd求最短路的实质是矩阵的自乘。( i , k )是第 i 行第k列,( k , j )是第k行第 j 列;用它们的max更新( i , j ),正是矩阵的自乘。
给一个矩阵赋予“已走 r 条边”的意义,则已走m条边的矩阵×已走n条边的矩阵得到的是已走m+n条边的矩阵。
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #define LL long long 5 #define mem(a, b) memset(a, b, sizeof(a)) 6 using namespace std; 7 const int inf = 0x3f3f3f3f; 8 9 int m, t, st, ed; 10 int h[1100], cnt; 11 12 struct Matrix 13 { 14 LL a[210][210]; 15 }ans; 16 17 Matrix floyd(Matrix a, Matrix b) 18 { 19 Matrix res; 20 mem(res.a, inf); 21 for(int k = 1; k <= cnt; k ++) 22 for(int i = 1; i <= cnt; i ++) 23 for(int j = 1; j <= cnt; j ++) 24 { 25 res.a[i][j] = min(res.a[i][j], a.a[i][k] + b.a[k][j]); 26 } 27 return res; 28 } 29 30 void Quick() 31 { 32 Matrix temp; 33 temp = ans; 34 m --; //加入 m - 1个点就形成了 m 条边 35 while(m) 36 { 37 if(m % 2) 38 ans = floyd(ans, temp); 39 temp = floyd(temp, temp); 40 m /= 2; 41 } 42 printf("%lld\n", ans.a[h[st]][h[ed]]); 43 } 44 45 int main() 46 { 47 scanf("%d%d%d%d", &m, &t, &st, &ed); 48 mem(ans.a, inf); 49 for(int i = 1; i <= t; i ++) 50 { 51 int val, a, b; 52 scanf("%d%d%d", &val, &a, &b); 53 if(!h[a]) //离散化 54 h[a] = ++ cnt; 55 if(!h[b]) 56 h[b] = ++ cnt; 57 ans.a[h[a]][h[b]] = ans.a[h[b]][h[a]] = min(ans.a[h[a]][h[b]], val * 1ll); 58 } 59 Quick(); 60 return 0; 61 }