图的矩阵乘法
给定一个N个节点的无向图(可以证明有向图也满足要求)
设G[u][v]=G[v][u]=1表示u,v有一条路径
我们模拟矩阵自乘G2[u][v]=
∑
(
i
=
1
,
n
)
G
[
u
]
[
i
]
∗
G
[
i
]
[
v
]
\sum(i=1,n)G[u][i]*G[i][v]
∑(i=1,n)G[u][i]∗G[i][v]
这表示u到v的路径上只经过中间点i的路径条数
即u到v的路径上经过两条边的路径条数
以此类推,Gk[u][v]表示在u到v的路径上经过k条边的路径条数
p.s.当路径上有重边时,G[u][v]表示u到v的路径条数
接下来,我们讨论求u到v经过k条边的最短路
设G[u][v]表示u到v仅经过一条边的最短路
G2[u][v]=Mini=1,n(G[u][i]+G[i][v]);
这个。。。很显然吧
他同样满足矩阵乘法的性质
所以可以愉快的快速幂了,只是把矩阵A[i][k]*B[k][j]定义为min{a[i][k]+b[k][j]}
例题:Cow Relays
P2886 [USACO07NOV]牛继电器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 ≤ 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.
给出一张无向连通图,求S到E经过k条边的最短路。
输入格式
-
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
输出格式
- Line 1: A single integer that is the shortest distance from intersection S to intersection E that traverses exactly N cow trails.
输入输出样例
输入 #1 复制
2 6 6 4
11 4 6
4 4 8
8 4 9
6 6 8
2 6 9
3 8 9
输出 #1 复制
10
对于这道题目的翻译,我已无力吐槽,差点没有双倍经验
直接上代码了
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
struct Matrix
{
long long v[210][210];
};
Matrix G,ans;
int K,T,S,E;
long long n;
long long p[2010];
inline long long min(long long x,long long y)
{
return x<y?x:y;
}
Matrix mul(Matrix a,Matrix b)
{
Matrix c;
memset(c.v,0x3f,sizeof(c.v));
int i,j,k;
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
c.v[i][j]=min(c.v[i][j],a.v[i][k]+b.v[k][j]);
return c;
}
void ksm(int x)
{
while(x)
{
if(x&1)
ans=mul(ans,G);
G=mul(G,G);
x>>=1;
}
}
int main()
{
freopen("relay.in","r",stdin);
freopen("relay.out","w",stdout);
int i;
scanf("%d%d%d%d",&K,&T,&S,&E);
memset(G.v,0x3f,sizeof(G.v));
memset(ans.v,0x3f,sizeof(ans.v));
for(i=1;i<=T;i++)
{
int w,x,y;
scanf("%d%d%d",&w,&x,&y);
if(!p[x]) p[x]=++n;
if(!p[y]) p[y]=++n;
G.v[p[x]][p[y]]=G.v[p[y]][p[x]]=min(w,G.v[p[y]][p[x]]);
}
for(i=1;i<=n;i++)
ans.v[i][i]=0;
ksm(K);
printf("%lld\n",ans.v[p[S]][p[E]]);
return 0;
}