zoukankan      html  css  js  c++  java
  • POJ3613--Cow Relays

    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
    懒得翻译(其实是不会)
    题意:从s点出发到达e点且经过n条边的最短路是多少(可以走重复的路径)

       思路:folyd可以实现向路径中添边,但是这题与普通的求最短路问题不一样,比如从S到E经过X条边后就已经达到了最短路,这个时候仍然要强制用floyd再添边,尽管添边后就不  是最短路了,但是要注意到添加的这边要使最短路损失最小,抓住这点用floyd可以实现强制添边的操作,所以可以从n=1的状态向n的状态转移,然后你会发现一个叫N (2 ≤ N ≤ 1,000,000) 的*&#¥%……@!**&#@¥!%¥……&东西,然后你炸了,所以要用快速幂去优化,这样的话你只用log(n)就能去找。

    还有一个最重要的方法,你要知道经过一点的一条路+经过一点的一条路=经过两点的一条路,依此类推可得经过两点的一条路+经过一点的一条路=经过三点的一条路。

    这个是矩阵相乘的一种方法,然后你会发现如果一个矩阵,表示走k条边后,一张图的点与点的最短路径,(a,b)表示从a到b的最短路径,然后我们把它与自己,按照矩阵乘法的格式“相乘”,把其中的乘改为取min,c.a[i][j] = min(c.a[i][j],x.a[i][k]+y.a[k][j])

    这样得到的是走k+k条边的矩阵。有点抽象,下面详细解释,如下

    c中的一个点(a,b),当我们用x矩阵和y矩阵求它时,我们枚举了x矩阵的a行所有数,与y矩阵的b列所有数,并且他们的坐标只能是相对应的,比如x矩阵的(a,2)这个点,相应的y矩阵点就是(2,b),那么放到图上去理解,即从a点经过2点到b点的距离,类似的点不只有2,把所有点枚举完后,c.a[a][b]就是从a到b的最短距离。(想象一下)

    这样下来,会得到走k+k条边的最短路径,对于其他的矩阵这样操作,得到的是他们两个,经过的边数相加的结果。(一个经过a条边后的矩阵 与 一个经过b条边后的矩阵这样操作后,是经过a+b条边后的矩阵,矩阵中存的是最短路径)。向上面的例子一样,(a,2)(2,b),是即从a点经过2点到b点的距离,因为x矩阵和y矩阵都是走k条边后的最短路径,那么x矩阵中的(a,2)是走k步后的最短路径,(2,b)也是,那么他们相加就是走加了K条边后的最短路径。

    然后,就可以套用快速幂的模板了,只不过将以前的乘改成加了,也就是倍增的思想的,比如对于走10条边,它的二进制是1010,那么我们就让在走2边时的矩阵 乘以 8边的矩阵,得到(用二进制去乘)走10条边的矩阵即开始时由1->2->4->8->16……即2的n次幂。

    代码:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<map>
     4 #include<cstring>
     5 #include<iostream>
     6 using namespace std;
     7 int k,t,sb,e;
     8 int ji=0;
     9 int head[11000];
    10 struct str{
    11     int a[201][201];
    12     str operator * (const str &x) const
    13     {
    14         str c;
    15         memset(c.a,0x3f,sizeof(c.a));
    16         for(int k=1;k<=ji;k++){
    17             for(int i=1;i<=ji;i++){
    18                 for(int j=1;j<=ji;j++){
    19                     c.a[i][j]=min(c.a[i][j],a[i][k]+x.a[k][j]);
    20                 }   
    21             }
    22         }
    23         return c;
    24     } 
    25 }s,ans;
    26 void quickly(){
    27     ans=s;
    28     k--;
    29     while(k)
    30     {
    31         if(k&1) ans=ans*s;
    32         k>>=1;
    33         s=s*s;
    34     }
    35 }
    36 int main(){
    37     cin>>k>>t>>sb>>e;
    38     memset(s.a,0x3f,sizeof(s.a));
    39     for(int i=1;i<=t;i++){
    40         int x,y,z;
    41         cin>>z>>x>>y;
    42         if(!head[x]) head[x]=++ji;
    43         if(!head[y]) head[y]=++ji;
    44         s.a[head[x]][head[y]]=z;
    45         s.a[head[y]][head[x]]=z;
    46     }
    47     quickly();
    48     cout<<ans.a[head[sb]][head[e]];
    49 }
    50 /*
    51 12 6 6 4
    52 11 4 6
    53 4 4 8
    54 8 4 9
    55 6 6 8
    56 2 6 9
    57 3 8 9
    58 */
  • 相关阅读:
    c++ 全局变量初始化的一点总结
    新的博客
    Git常用命令总结
    git 分支 branch 操作
    状态管理Vuex
    让 markdown 生成带目录的 html 文件
    mysql安装时,提示:Failed to start service MYSQL80
    【React 资料备份】React Hook
    【React 资料备份】React v16.3之后的生命周期
    两个数组对象取并集
  • 原文地址:https://www.cnblogs.com/dai-jia-ye/p/11068595.html
Copyright © 2011-2022 走看看