Cow Relays
题目传送门
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 ≤ I_{1i} ≤ 1,000; 1 ≤ I_{2i} ≤ 1,000)), each of which is the termination for at least two trails. The cows know the lengthi of each trail ((1 ≤ length_i ≤ 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: (length_i) , (I_{1i}) , and (I_{2i})
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
Solve
看见数据范围,边的数量不大于100,那么点的数量也就不到100,既然是最短路,那就想到Folyd算法
//板子
for(int k = 1; k <= n; k++)
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
f[i][j] = min(f[i][j], f[i][k] + f[k][j])
这个很简单
然后,我们假设a数组是通过了x条边的最短路,b数组是通过了y条边的最短路
for(int k = 1; k <= tot; k++)
for(int i = 1; i <= tot; i++)
for(int j = 1; j <= tot; j++)
c[i][j] = min(c[i][j], a[i][k] + b[k][j]);
通过这样,显然我们就得到了c数组是通过了(x+y)条边的最短路
要经过N条边,就是对原来的邻接矩阵进行N-1操作就行
矩阵快速幂
我们把每一次操作看成一次矩阵乘法,就可以用矩阵快速幂来优化
快速幂
int Pow(int a, int x) {
int ans = 1;
for (; x; x >>= 1, a = (ll)a * a % M)
if (x & 1) ans = (ll)ans * a % M;
return ans;
}
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n, k, s, t, m[1005], tot;
struct node {
int a[105][105];
node operator * (const node& b) const {
node c;
memset(c.a, 0x3f, sizeof(c.a));
for(int k = 1; k <= tot; k++)
for(int i = 1; i <= tot; i++)
for(int j = 1; j <= tot; j++)
c.a[i][j] = min(c.a[i][j], a[i][k] + b.a[k][j]);
return c;
}//重载运算符 *
}a;//定义矩阵结构体
node qpow(node a, int x) {
node ans = a;
x--;
while (x) {
if (x & 1) ans = ans * a;
x >>= 1;
a = a * a;
}
return ans;
}//快速幂
int main() {
memset(a.a, 0x3f, sizeof(a.a));
scanf("%d%d%d%d", &k, &n, &s, &t);
for(int i = 1, x, y, z; i <= n; i++) {
scanf("%d%d%d", &z, &x, &y);
if (!m[x]) m[x] = ++tot;
if (!m[y]) m[y] = ++tot;
//这里是离散化
a.a[m[x]][m[y]] = a.a[m[y]][m[x]] = z;
}
a = qpow(a, k);
printf("%d", a.a[m[s]][m[t]]);
//注意已经进行了离散化
return 0;
}