zoukankan      html  css  js  c++  java
  • [USACO 07NOV]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.

    给出一张无向连通图,求S到E经过k条边的最短路。

    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: 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

    题解

    解法一:

    考虑有用的点数很少,我们可以哈希一下,建立邻接矩阵,矩阵加速求出经过$N$条边的从$S$到$T$的最短路。

     1 #include<set>
     2 #include<map>
     3 #include<stack>
     4 #include<ctime>
     5 #include<cmath>
     6 #include<queue>
     7 #include<string>
     8 #include<cstdio>
     9 #include<vector>
    10 #include<cstdlib>
    11 #include<cstring>
    12 #include<iostream>
    13 #include<algorithm>
    14 #define LL long long
    15 #define RE register
    16 #define IL inline
    17 using namespace std;
    18 const int INF=1e9;
    19 
    20 IL int Min(int a,int b){return a<b ? a:b;}
    21 
    22 int num[1005],pos;
    23 int f[205][205];
    24 int k,m,s,e,u,v,l;
    25 struct mat
    26 {
    27     int a[205][205];
    28     mat() {for (int i=1;i<=pos;i++)for (int j=1;j<=pos;j++) a[i][j]=INF;}
    29     mat operator * (const mat &b)
    30     {
    31         mat ans;
    32         for (RE int i=1;i<=pos;i++)
    33             for (RE int j=1;j<=pos;j++)
    34                 for (RE int k=1;k<=pos;k++)
    35                     ans.a[i][j]=Min(ans.a[i][j],a[i][k]+b.a[k][j]);
    36         return ans;
    37     }
    38 };
    39 
    40 int main()
    41 {
    42     scanf("%d%d%d%d",&k,&m,&s,&e);
    43     for (RE int i=1;i<=m;i++)
    44     {
    45         scanf("%d%d%d",&l,&u,&v);
    46         if (!num[u]) num[u]=++pos;
    47         if (!num[v]) num[v]=++pos;
    48         f[num[u]][num[v]]=f[num[v]][num[u]]=l;
    49     }
    50     mat S,T;
    51     for (RE int i=1;i<=pos;i++) for (RE int j=1;j<=pos;j++) if (f[i][j]) S.a[i][j]=T.a[i][j]=f[i][j];
    52     k--;
    53     while (k)
    54     {
    55         if (k&1) S=S*T;
    56         k>>=1;
    57         T=T*T;
    58     }
    59     printf("%d
    ",S.a[num[s]][num[e]]);
    60     return 0;
    61 }
    矩乘

    解法二:

    利用倍增的思想。令$f[i][j][t]$表示从$i$到$j$经过$2^t$条边的最优值,做一遍$floyd$再统计答案即可。

     1 #include<cmath>
     2 #include<queue>
     3 #include<ctime>
     4 #include<stack>
     5 #include<cstdio>
     6 #include<string>
     7 #include<cstdlib>
     8 #include<cstring>
     9 #include<iostream>
    10 #include<algorithm>
    11  using namespace std;
    12 const int INF=1e9;
    13 
    14 int num[1005],pos;
    15 int f[205][205][25];
    16 int towards[205][2];
    17 bool t;
    18 int k,m,s,e,u,v,l;
    19 
    20 int main()
    21 {
    22     memset(f,127/3,sizeof(f));
    23     memset(towards,127/3,sizeof(towards));
    24     scanf("%d%d%d%d",&k,&m,&s,&e);
    25     for (int i=1;i<=m;i++)
    26     {
    27         scanf("%d%d%d",&l,&u,&v);
    28         if (!num[u]) num[u]=++pos;
    29         if (!num[v]) num[v]=++pos;
    30         f[num[u]][num[v]][0]=f[num[v]][num[u]][0]=l;
    31     }
    32     int lim=log2(k);
    33     for (int p=1;p<=lim;p++)
    34         for (int q=1;q<=pos;q++)
    35             for (int i=1;i<=pos;i++)
    36                 for (int j=1;j<=pos;j++)// if (i!=j&&q!=i)
    37                     if (f[i][j][p]>f[i][q][p-1]+f[q][j][p-1])
    38                         f[i][j][p]=f[i][q][p-1]+f[q][j][p-1];
    39     int p=0;
    40     towards[num[s]][t]=0;
    41     while (k!=0)
    42     {
    43         if (k&1)
    44         {
    45             t=!t;
    46             for (int i=1;i<=pos;i++)
    47             {
    48                 towards[i][t]=INF;
    49                 for (int j=1;j<=pos;j++)
    50                     if (towards[i][t]>towards[j][!t]+f[i][j][p])
    51                         towards[i][t]=towards[j][!t]+f[i][j][p];
    52             }
    53         }
    54         p++;
    55         k=k>>1;
    56     }
    57     printf("%d
    ",towards[num[e]][t]);
    58     return 0;
    59 }
    倍增
  • 相关阅读:
    增强资源管理器右键功能,含源代码
    VC中结构体的内存布局
    进程间共享句柄三种方式
    Delphi获取CPU CPUID《转》
    Delphi中判断WebBrowser的页面是否加载完成 《转》
    Delphi 防止程序多次运行《转》
    界面显示后延时运行代码《转》
    界面显示后延时运行代码《转》
    DIV布局-DIV高度不同自动换行并对齐《转》
    Delphi 语句块《LceMeaning》
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7364890.html
Copyright © 2011-2022 走看看