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 }
View Code

 

posted @ 2019-10-10 19:57  缘未到  阅读(148)  评论(0编辑  收藏  举报