POJ3613 Cow Relays 矩阵快速幂 Floyd
Cow Relays
For their physical fitness program,
$ N (2 \le N \le 1,000,000) $ cows have decided to run a relay race
using the $ T (2 \le T \le 100) $ cow trails throughout the pasture.
Each trail connects two different intersections $ (1 \le I_{1i} \le 1,000; 1 \le I_{2i} \le 1,000) $ ,
each of which is the termination for at least two trails.
The cows know the $ length_i $ of each trail $ (1 \le length_i \le 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
Source
题目大意
-
给定一张由 $ T (2 \le T \le 100 ) $ 条边构成的无向图,点的编号为 $ 1 ~ 1000 $ 之间的整数。
-
求从起点 $ S $ 到终点 $ E $ 恰好经过 $ N (2 \le N \le 1000000) $ 条边(可重复经过)的最短路。
题解
-
点的标号离散化到 $ 1 ~ P $
-
若矩阵 $ A^m $ 保存任意两点之间恰好经过 $ m $ 条边的最短路,则:
-
上式其实等价于一个关于 $ min $ 与加法运算的广义“矩阵乘法”。
-
$ (A^N)[S,E] $ 即为本题的答案。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,t,s,e,mp[1010],cnt;
struct data{
int a[205][205];
data operator *(data &x){
data c; memset(c.a,0x3f,sizeof(c.a));
for(int i=1;i<=cnt;++i)
for(int j=1;j<=cnt;++j)
for(int k=1;k<=cnt;++k)
c.a[i][j]=min(c.a[i][j],a[i][k]+x.a[k][j]);
return c;
}
}st,ans;
void qpow(){
ans=st; --n;
while(n){
if(n&1) ans=ans*st;
st=st*st;
n>>=1;
}
}
int main(){
scanf("%d %d %d %d",&n,&t,&s,&e);
memset(st.a,0x3f,sizeof(st.a));
for(int w,u,v,i=1;i<=t;++i){
scanf("%d %d %d",&w,&u,&v);
if(mp[u]) u=mp[u]; else u=mp[u]=++cnt;
if(mp[v]) v=mp[v]; else v=mp[v]=++cnt;
st.a[u][v]=st.a[v][u]=w;
}
qpow();
printf("%d",ans.a[mp[s]][mp[e]]);
return 0;
}
/*
Problem: 3613
User: potremz
Memory: 788K
Time: 297MS
Language: C++
Result: Accepted
*/