【SSL 2510】[洛谷P2886]Cow Relays G【矩阵乘法の变形】

题目大意

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 n1次即可.

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;
}

猜你喜欢

转载自blog.csdn.net/dgssl_xhy/article/details/111404976