Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions:9207 | Accepted: 3604 |
Description
For their physical fitness program, N (2 ≤ N ≤ 1,000,000) cows have decided to run a relay race using the T (2 ≤ T ≤ 100) cow trails throughout the pasture.
Each trail connects two different intersections (1 ≤ I1i ≤ 1,000; 1 ≤ I2i ≤ 1,000), each of which is the termination for at least two trails. The cows know the lengthi of each trail (1 ≤ lengthi ≤ 1,000), the two intersections the trail connects, and they know that no two intersections are directly connected by two different trails. The trails form a structure known mathematically as a graph.
To run the relay, the N cows position themselves at various intersections (some intersections might have more than one cow). They must position themselves properly so that they can hand off the baton cow-by-cow and end up at the proper finishing place.
Write a program to help position the cows. Find the shortest path that connects the starting intersection (S) and the ending intersection (E) and traverses exactly N cow trails.
Input
* Line 1: Four space-separated integers: N, T, S, and E
* Lines 2..T+1: Line i+1 describes trail i with three space-separated integers: lengthi , I1i , and I2i
Output
* Line 1: A single integer that is the shortest distance from intersection S to intersection E that traverses exactly N cow trails.
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
Source
题意:
在一个图上求从$S$到$E$的,刚好经过$n$条边的最短路径长。
思路:
没想到最短路的题目还可以用快速幂。也没想到快速幂还可以这么写。
这道题边最多是100条,所以可以先把点离散化。离散化后点的编号最大是$node_cnt$
最初的矩阵$G[i,j]$中存储的其实是从$i$经过一条边到达$j$的最短路
那么$G^{(2)}[i, j] = min_{1leq kleq node_cnt}{G[i, k] + G[k, j]}$就可以表示从$i$经过两条边到达$j$的最短路
如果矩阵$G^{(m)}$表示任意两点之间恰好经过$m$条边的最短路,那么
$G^{(r+m)}[i, j] = min_{1leq kleq node_cnt}{G^{(r)}[i, k] + G^{(m)}[k, j]}$
这就可以使用快速幂进行递推了。只需要把$matrix$的乘法操作中,$+=$变成$min$, $*$变成$+$
注意矩阵要初始化为$+infty$
1 #include<iostream> 2 //#include<bits/stdc++.h> 3 #include<cstdio> 4 #include<cmath> 5 #include<cstdlib> 6 #include<cstring> 7 #include<algorithm> 8 #include<queue> 9 #include<vector> 10 #include<set> 11 #include<climits> 12 #include<map> 13 using namespace std; 14 typedef long long LL; 15 #define N 100010 16 #define pi 3.1415926535 17 #define inf 0x3f3f3f3f 18 19 int n, t, S, E; 20 const int maxn = 105; 21 int node_cnt; 22 struct matrix{ 23 int m[maxn][maxn]; 24 //int m_size; 25 matrix operator *(const matrix &b)const{ 26 matrix ret; 27 memset(ret.m, 0x3f, sizeof(ret.m)); 28 for(int i = 1; i <= node_cnt; i++){ 29 for(int j = 1; j <= node_cnt; j++){ 30 //ret.m[i][j] = inf; 31 for(int k = 1; k <= node_cnt; k++){ 32 ret.m[i][j] = min(m[i][k] + b.m[k][j], ret.m[i][j]); 33 } 34 } 35 } 36 return ret; 37 } 38 }g; 39 //int g[maxn][maxn]; 40 struct edge{ 41 int u, v, length; 42 }e[105]; 43 set<int>nodes; 44 set<int>::iterator set_it; 45 map<int, int>node_mp; 46 47 48 matrix ksm(matrix a, int x) 49 { 50 matrix ret, k; 51 k = a; 52 ret = a; 53 x--; 54 while(x){ 55 if(x & 1){ 56 ret = ret * k; 57 } 58 x >>= 1; 59 k = k * k; 60 } 61 return ret; 62 } 63 64 65 int main() 66 { 67 while(scanf("%d%d%d%d", &n, &t, &S, &E) != EOF){ 68 for(int i = 0; i < t; i++){ 69 scanf("%d%d%d", &e[i].length, &e[i].u, &e[i].v); 70 nodes.insert(e[i].u); 71 nodes.insert(e[i].v); 72 } 73 74 node_cnt = 0; 75 for(set_it = nodes.begin(); set_it != nodes.end(); set_it++){ 76 node_mp[*set_it] = ++node_cnt; 77 } 78 //g.m_size = node_cnt; 79 memset(g.m, 0x3f, sizeof(g.m)); 80 for(int i = 0; i < t; i++){ 81 int u = e[i].u, v = e[i].v; 82 g.m[node_mp[u]][node_mp[v]] = e[i].length; 83 g.m[node_mp[v]][node_mp[u]] = e[i].length; 84 } 85 /*for(int i = 1; i <= node_cnt; i++){ 86 for(int j = 1; j <= node_cnt; j++){ 87 cout<<g.m[i][j]<<" "; 88 } 89 cout<<endl; 90 }*/ 91 92 matrix ans = ksm(g, n); 93 //cout<<node_mp[S]<<" "<<node_mp[E]<<endl; 94 printf("%d ", ans.m[node_mp[S]][node_mp[E]]); 95 } 96 return 0; 97 }