题目大意
l i n k link link
给定一张 T 条边的无向连通图,求从 S 到 E 经过 N 条边的最短路长度。
输入格式
第一行四个正整数 N , T , S , E N,T,S,E N,T,S,E ,意义如题面所示。
接下来 T 行每行三个正整数 w , u , v w,u,v w,u,v ,分别表示路径的长度,起点和终点。
输出格式
一行一个整数表示图中从 S S S 到 E E E 经过 N N N 条边的最短路长度。
输入输出样例
输入 #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
分析:
其实把矩阵乘法做一点小改动就可以了
然后给这些顶点一个编号 然后就可以做邻接矩阵的矩阵快速幂
注意求的是最短路 所以把运算符重载成 ′ + ′ '+' ′+′
根据输入的初始数组转移 n − 1 n-1 n−1次即可.
CODE:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define reg register
using namespace std;
int u[1000005];
int n,s,t,e,tot,w,x,y;
const int N=505;
struct matrix{
int F[N][N];}dis,C;
matrix operator +(const matrix &x,const matrix &y)
{
matrix c;
memset(c.F,0x3f3f3f3f,sizeof(c.F));
for(reg int k=1;k<=tot;k++)
for(reg int i=1;i<=tot;i++)
for(reg int j=1;j<=tot;j++)
c.F[i][j]=min(c.F[i][j],x.F[i][k]+y.F[k][j]); //最短路
return c;
}
void check_x(){
if(!u[x]) u[x]=++tot;}
void check_y(){
if(!u[y]) u[y]=++tot;}
void build_map(int x,int y,int z){
dis.F[x][y]=dis.F[y][x]=z;}
void Pre()
{
memset(dis.F,0x3f3f3f3f,sizeof(dis.F));
scanf("%d%d%d%d",&n,&t,&s,&e);
for(reg int i=1;i<=t;i++)
{
scanf("%d%d%d",&w,&x,&y);
check_x();check_y(); //编号
build_map(u[x],u[y],w); //邻接矩阵
}
}
void ksm(int x)
{
C=dis;
while(x)
{
if(x&1) C=C+dis;
dis=dis+dis;
x>>=1;
}
}
int main()
{
Pre();
ksm(n-1); //转移n-1次
printf("%d",C.F[u[s]][u[e]]);
return 0;
}