POJ3613 Cow Relays 矩阵快速幂 Floyd

$ \rightarrow $ 戳我看POJ原题

Cow Relays
Time Limit: 1000MS $ \quad $ Memory Limit: 65536K

 

Description

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

USACO 2007 November Gold

 

题目大意

  • 给定一张由 $ T (2 \le T \le 100 ) $ 条边构成的无向图,点的编号为 $ 1 ~ 1000 $ 之间的整数。

  • 求从起点 $ S $ 到终点 $ E $ 恰好经过 $ N (2 \le N \le 1000000) $ 条边(可重复经过)的最短路。

 

题解

  • 点的标号离散化到 $ 1 ~ P $

  • 若矩阵 $ A^m $ 保存任意两点之间恰好经过 $ m $ 条边的最短路,则:

\[ \forall i,j \in [1,P], \quad (A^{r+m})[i,j]=min_{1 \le k \le P}((A^r)[i,k]+(A^m)[k,j]) \]

  • 上式其实等价于一个关于 $ 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
*/

转载于:https://www.cnblogs.com/PotremZ/p/POJ3613.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是Java解决POJ3233—矩阵幂序列问题的代码和解释: ```java import java.util.Scanner; public class Main { static int n, k, m; static int[][] A, E; public static void main(String[] args) { Scanner sc = new Scanner(System.in); n = sc.nextInt(); k = sc.nextInt(); m = sc.nextInt(); A = new int[n][n]; E = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { A[i][j] = sc.nextInt() % m; E[i][j] = (i == j) ? 1 : 0; } } int[][] res = matrixPow(A, k); int[][] ans = matrixAdd(res, E); printMatrix(ans); } // 矩阵乘法 public static int[][] matrixMul(int[][] a, int[][] b) { int[][] c = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { for (int k = 0; k < n; k++) { c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % m; } } } return c; } // 矩阵快速幂 public static int[][] matrixPow(int[][] a, int b) { int[][] res = E; while (b > 0) { if ((b & 1) == 1) { res = matrixMul(res, a); } a = matrixMul(a, a); b >>= 1; } return res; } // 矩阵加法 public static int[][] matrixAdd(int[][] a, int[][] b) { int[][] c = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { c[i][j] = (a[i][j] + b[i][j]) % m; } } return c; } // 输出矩阵 public static void printMatrix(int[][] a) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { System.out.print(a[i][j] + " "); } System.out.println(); } } } ``` 解释: 1. 首先读入输入的n、k、m和矩阵A,同时初始化单位矩阵E。 2. 然后调用matrixPow函数求出A的k次幂矩阵res。 3. 最后将res和E相加得到结果ans,并输出。 4. matrixMul函数实现矩阵乘法,matrixPow函数实现矩阵快速幂,matrixAdd函数实现矩阵加法,printMatrix函数实现输出矩阵。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值