(floyd+矩阵快速幂)POJ 3613 - Cow Relays
题意:
给一个无向带权图,求从s到t走k次的最短路。
分析:
一开始没想到,其实应该想到的,看到这种k很大,而且精确k次的题目,第一个一定要考虑快速幂。
而这题就是矩阵快速幂,而乘法的过程不是普通乘法,以为给的邻接矩阵表示的花费,所以只有相加才能计算两次走路的花费。
而最短路就是运用floyd的思想进行“乘法”。
每次乘法求最短路,计算k次,就是矩阵快速幂。
代码:
1 #include <set> 2 #include <map> 3 #include <list> 4 #include <cmath> 5 #include <queue> 6 #include <stack> 7 #include <vector> 8 #include <bitset> 9 #include <string> 10 #include <cctype> 11 #include <cstdio> 12 #include <cstring> 13 #include <cstdlib> 14 #include <iostream> 15 #include <algorithm> 16 // #include <unordered_map> 17 18 using namespace std; 19 20 typedef long long ll; 21 typedef unsigned long long ull; 22 typedef pair<int, int> pii; 23 typedef pair<ull, ull> puu; 24 25 #define inf (0x3f3f3f3f) 26 #define lnf (0x3f3f3f3f3f3f3f3f) 27 #define eps (1e-9) 28 #define fi first 29 #define se second 30 31 bool sgn(double a, string select, double b) { 32 if(select == "==")return fabs(a - b) < eps; 33 if(select == "!=")return fabs(a - b) > eps; 34 if(select == "<")return a - b < -eps; 35 if(select == "<=")return a - b < eps; 36 if(select == ">")return a - b > eps; 37 if(select == ">=")return a - b > -eps; 38 } 39 40 41 //-------------------------- 42 43 const ll mod = 1000000007; 44 const int maxn = 100010; 45 46 47 48 49 50 51 52 int k, m, s, e; 53 map<int, int> mm; 54 int cnt = 0; 55 56 57 struct Martix { 58 int maps[210][210]; 59 60 Martix operator*(const Martix &m)const { 61 Martix res; 62 memset(res.maps, inf, sizeof(res.maps)); 63 for(int i = 0; i < cnt; i++) { 64 for(int j = 0; j < cnt; j++) { 65 for(int k = 0; k < cnt; k++) { 66 res.maps[i][j] = min(maps[i][k] + m.maps[k][j], res.maps[i][j]); 67 } 68 } 69 } 70 return res; 71 } 72 73 74 Martix operator^(const ll &b)const { 75 ll num = b; 76 Martix res; 77 Martix tmp = *this; 78 memset(res.maps, inf, sizeof(res.maps)); 79 for(int i = 0; i < cnt; i++)res.maps[i][i] = 0; 80 while(num) { 81 if(num & 1)res = res * tmp; 82 tmp = tmp * tmp; 83 num >>= 1; 84 } 85 return res; 86 } 87 }; 88 89 90 91 92 void solve() { 93 while(~scanf("%d%d%d%d", &k, &m, &s, &e)) { 94 int w, u, v; 95 mm.clear(); 96 Martix A; 97 cnt = 0; 98 memset(A.maps, inf, sizeof(A.maps)); 99 for(int i = 0; i < m; i++) { 100 scanf("%d%d%d", &w, &u, &v); 101 if(mm.find(u) == mm.end()) { 102 mm[u] = cnt++; 103 } 104 if(mm.find(v) == mm.end()) { 105 mm[v] = cnt++; 106 } 107 A.maps[mm[u]][mm[v]] = w; 108 A.maps[mm[v]][mm[u]] = w; 109 } 110 111 Martix B = A ^ k; 112 // for(int i = 0; i < cnt; i++) { 113 // for(int j = 0; j < cnt; j++) { 114 // printf("%d ", B.maps[i][j] ); 115 // } 116 // puts(""); 117 // } 118 printf("%d\n", B.maps[mm[s]][mm[e]]) ; 119 } 120 121 } 122 123 int main() { 124 125 #ifndef ONLINE_JUDGE 126 freopen("1.in", "r", stdin); 127 freopen("1.out", "w", stdout); 128 #endif 129 // iostream::sync_with_stdio(false); 130 solve(); 131 return 0; 132 }