zoukankan      html  css  js  c++  java
  • 2D poj Cow Relays——folyd+矩阵快速幂

    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 ≤ I_{1i} ≤ 1,000; 1 ≤ I_{2i} ≤ 1,000)), each of which is the termination for at least two trails. The cows know the lengthi of each trail ((1 ≤ length_i ≤ 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
    

    Solve

    看见数据范围,边的数量不大于100,那么点的数量也就不到100,既然是最短路,那就想到Folyd算法

    //板子
    for(int k = 1; k <= n; k++)
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                f[i][j] = min(f[i][j], f[i][k] + f[k][j])
    

    这个很简单

    然后,我们假设a数组是通过了x条边的最短路,b数组是通过了y条边的最短路

    for(int k = 1; k <= tot; k++)
        for(int i = 1; i <= tot; i++)
            for(int j = 1; j <= tot; j++)
                c[i][j] = min(c[i][j], a[i][k] + b[k][j]);
    

    通过这样,显然我们就得到了c数组是通过了(x+y)条边的最短路

    要经过N条边,就是对原来的邻接矩阵进行N-1操作就行

    矩阵快速幂
    我们把每一次操作看成一次矩阵乘法,就可以用矩阵快速幂来优化

    快速幂

    int Pow(int a, int x) {
        int ans = 1;
        for (; x; x >>= 1, a = (ll)a * a % M)
            if (x & 1) ans = (ll)ans * a % M;
        return ans;
    }
    

    Code

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    int n, k, s, t, m[1005], tot;
    struct node {
        int a[105][105];
        node operator * (const node& b) const {
            node c;
            memset(c.a, 0x3f, sizeof(c.a));
            for(int k = 1; k <= tot; k++)
                for(int i = 1; i <= tot; i++)
                    for(int j = 1; j <= tot; j++)
                        c.a[i][j] = min(c.a[i][j], a[i][k] + b.a[k][j]);
            return c;
        }//重载运算符 * 
    }a;//定义矩阵结构体
    node qpow(node a, int x) {
        node ans = a;
        x--;
        while (x) {
            if (x & 1) ans = ans * a;
            x >>= 1;
            a = a * a;
        }
        return ans;
    }//快速幂
    int main() {
        memset(a.a, 0x3f, sizeof(a.a));
        scanf("%d%d%d%d", &k, &n, &s, &t);
        for(int i = 1, x, y, z; i <= n; i++) {
            scanf("%d%d%d", &z, &x, &y);
            if (!m[x]) m[x] = ++tot;
            if (!m[y]) m[y] = ++tot;
            //这里是离散化
            a.a[m[x]][m[y]] = a.a[m[y]][m[x]] = z;
        }
        a = qpow(a, k);
        printf("%d", a.a[m[s]][m[t]]);
        //注意已经进行了离散化
        return 0;
    }
    
  • 相关阅读:
    Educational Codeforces Round 59 (Rated for Div. 2)E. Vasya and Binary String 区间dp
    MySQL语法大全
    D. Buy a Ticket(优先队列+dijkstra)
    Two Sets(并查集分类)
    KMP浅显易懂
    深度理解链式前向星
    快速幂(幂运算取模的logn算法)
    hdu---1950---Bridging signals解题报告(求Lis n*logn贪心+二分搜索)
    dp背包
    线段树模板
  • 原文地址:https://www.cnblogs.com/shawk/p/12793956.html
Copyright © 2011-2022 走看看