zoukankan      html  css  js  c++  java
  • poj3613 Cow Relays【好题】【最短路】【快速幂】【离散化】

    Cow Relays
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions:9207   Accepted: 3604

    Description

    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: NTS, 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.

    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

    题意:

    在一个图上求从$S$到$E$的,刚好经过$n$条边的最短路径长。

    思路:

    没想到最短路的题目还可以用快速幂。也没想到快速幂还可以这么写。

    这道题边最多是100条,所以可以先把点离散化。离散化后点的编号最大是$node_cnt$

    最初的矩阵$G[i,j]$中存储的其实是从$i$经过一条边到达$j$的最短路

    那么$G^{(2)}[i, j] = min_{1leq kleq node_cnt}{G[i, k] + G[k, j]}$就可以表示从$i$经过两条边到达$j$的最短路

    如果矩阵$G^{(m)}$表示任意两点之间恰好经过$m$条边的最短路,那么

    $G^{(r+m)}[i, j] = min_{1leq kleq node_cnt}{G^{(r)}[i, k] + G^{(m)}[k, j]}$

    这就可以使用快速幂进行递推了。只需要把$matrix$的乘法操作中,$+=$变成$min$, $*$变成$+$

    注意矩阵要初始化为$+infty$

     1 #include<iostream>
     2 //#include<bits/stdc++.h>
     3 #include<cstdio>
     4 #include<cmath>
     5 #include<cstdlib>
     6 #include<cstring>
     7 #include<algorithm>
     8 #include<queue>
     9 #include<vector>
    10 #include<set>
    11 #include<climits>
    12 #include<map>
    13 using namespace std;
    14 typedef long long LL;
    15 #define N 100010
    16 #define pi 3.1415926535
    17 #define inf 0x3f3f3f3f
    18 
    19 int n, t, S, E;
    20 const int maxn = 105;
    21 int node_cnt;
    22 struct matrix{
    23     int m[maxn][maxn];
    24     //int m_size;
    25     matrix operator *(const matrix &b)const{
    26         matrix ret;
    27         memset(ret.m, 0x3f, sizeof(ret.m));
    28         for(int i = 1; i <= node_cnt; i++){
    29             for(int j = 1; j <= node_cnt; j++){
    30                 //ret.m[i][j] = inf;
    31                 for(int k = 1; k <= node_cnt; k++){
    32                     ret.m[i][j] = min(m[i][k] + b.m[k][j], ret.m[i][j]);
    33                 }
    34             }
    35         }
    36         return ret;
    37     }
    38 }g;
    39 //int g[maxn][maxn];
    40 struct edge{
    41     int u, v, length;
    42 }e[105];
    43 set<int>nodes;
    44 set<int>::iterator set_it;
    45 map<int, int>node_mp;
    46 
    47 
    48 matrix ksm(matrix a, int x)
    49 {
    50     matrix ret, k;
    51     k = a;
    52     ret = a;
    53     x--;
    54     while(x){
    55         if(x & 1){
    56             ret = ret * k;
    57         }
    58         x >>= 1;
    59         k = k * k;
    60     }
    61     return ret;
    62 }
    63 
    64 
    65 int main()
    66 {
    67     while(scanf("%d%d%d%d", &n, &t, &S, &E) != EOF){
    68         for(int i = 0; i < t; i++){
    69             scanf("%d%d%d", &e[i].length, &e[i].u, &e[i].v);
    70             nodes.insert(e[i].u);
    71             nodes.insert(e[i].v);
    72         }
    73 
    74         node_cnt = 0;
    75         for(set_it = nodes.begin(); set_it != nodes.end(); set_it++){
    76             node_mp[*set_it] = ++node_cnt;
    77         }
    78         //g.m_size = node_cnt;
    79         memset(g.m, 0x3f, sizeof(g.m));
    80         for(int i = 0; i < t; i++){
    81             int u = e[i].u, v = e[i].v;
    82             g.m[node_mp[u]][node_mp[v]] = e[i].length;
    83             g.m[node_mp[v]][node_mp[u]] = e[i].length;
    84         }
    85         /*for(int i = 1; i <= node_cnt; i++){
    86             for(int j = 1; j <= node_cnt; j++){
    87                 cout<<g.m[i][j]<<" ";
    88             }
    89             cout<<endl;
    90         }*/
    91 
    92         matrix ans = ksm(g, n);
    93         //cout<<node_mp[S]<<" "<<node_mp[E]<<endl;
    94         printf("%d
    ", ans.m[node_mp[S]][node_mp[E]]);
    95     }
    96     return 0;
    97 }
  • 相关阅读:
    导出 IIS 站点及配置
    redis
    mongo常用
    mongo分片集群
    mysql常用
    elk安装
    Oracle数据库迁移文档
    笔记
    ping 。sh
    光衰报警
  • 原文地址:https://www.cnblogs.com/wyboooo/p/9973027.html
Copyright © 2011-2022 走看看