Time limit1000 ms
Memory limit65536 kB
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.
题目分析
图的邻接矩阵有一个性质
若
表示
到
恰好经过一条边的路径的条数
那么
则表示恰好经过
条边的
可以用矩阵快速幂计算
这题我们对矩阵乘法的定义稍加修改
我们把原先矩乘的乘法改成加法,求和改成求最小值
即
若
表示
到
恰好经过一条边的路径的最短路
那么
则表示恰好经过
条边的
重新定义计算后依然满足结合律,可以使用矩阵快速幂计算
上述在这篇博客中都有具体解释
矩阵乘法 x 图的邻接矩阵
注意此题需要将节点编号离散化
#include<iostream>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
int read()
{
int f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return f*x;
}
const int maxn=500;
int n,m,s,t,tot;
int hh[1000010];
struct node{int a[maxn][maxn];}rem;
node mul(node x,node y)
{
node ans;
memset(ans.a,63,sizeof(ans.a));
for(int k=1;k<=tot;++k)
for(int i=1;i<=tot;++i)
for(int j=1;j<=tot;++j)
ans.a[i][j]=min(ans.a[i][j],x.a[i][k]+y.a[k][j]);
return ans;
}
node qpow(node a,int k)
{
node ans=a; k--;
while(k>0){
if(k&1) ans=mul(ans,a);
a=mul(a,a);
k>>=1;
}
return ans;
}
int main()
{
n=read();m=read();s=read();t=read();
memset(rem.a,63,sizeof(rem.a));
for(int i=1;i<=m;++i)
{
int dis=read(),u=read(),v=read();
if(!hh[u]) hh[u]=++tot;
if(!hh[v]) hh[v]=++tot;
if(rem.a[hh[u]][hh[v]]>dis)
rem.a[hh[u]][hh[v]]=rem.a[hh[v]][hh[u]]=dis;
}
node tt=qpow(rem,n);
printf("%d",tt.a[hh[s]][hh[t]]);
return 0;
}