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 }
    倍增
  • 相关阅读:
    牛客IOI周赛17-提高组 卷积 生成函数 多项式求逆 数列通项公式
    6.3 省选模拟赛 Decompose 动态dp 树链剖分 set
    AtCoder Grand Contest 044 A Pay to Win 贪心
    5.29 省选模拟赛 树的染色 dp 最优性优化
    luogu P6097 子集卷积 FST FWT
    CF724C Ray Tracing 扩展欧几里得 平面展开
    5.30 省选模拟赛 方格操作 扫描线 特殊性质
    5.29 省选模拟赛 波波老师 SAM 线段树 单调队列 并查集
    Spring main方法中怎么调用Dao层和Service层的方法
    Bug -- WebService报错(两个类具有相同的 XML 类型名称 "{http://webService.com/}getPriceResponse"。请使用 @XmlType.name 和 @XmlType.namespace 为类分配不同的名称。)
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7364890.html
Copyright © 2011-2022 走看看