• [USACO09DEC]牛收费路径Cow Toll Paths


    题目大意:给定一个无向图,求出一条路径,使得边权和加上点权和最小,多组询问

    n<=250 m<=10000

    多组询问,数据范围这么小,很显然就是floyd了,但是这个点权着实让人讨厌哇。。。

    我们重新回想一遍floyd算法的原理:i到j有两种可能:直接到和借助中间接口k,所以取一个min就行了

    我们再往下细细的想一下,k代表的是中间的接口,而且k的枚举顺序是任意的?

    显然是任意的!突破口就在这:我们可以肆意的修改k的枚举顺序!

    所以,这道题就解决了,我们只要从小到大枚举k,跑flyod,点权最大值利用min(c[i],c[j],c[k])来维护就行了!

    正确性?

    当我们枚举到一个k的时候,就代表路径中除了i,j以外没有任何数可能比k大,所以我们在三个中取一个min就行了

    时间复杂度:O(n^3)

    注意处理细节:例如枚举后顺序改变等

    最后,附上本题代码:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<iostream>
     6 using namespace std;
     7 //Debug Yufenglin
     8 #define dej printf("Running
    ");
     9 #define dep1(x) cout<<#x<<"="<<x<<endl;
    10 #define dep2(x,y) cout<<#x<<"="<<x<<' '<<#y<<"="<<y<<endl;
    11 #define dep3(x,y,z) cout<<#x<<"="<<x<<' '<<#y<<"="<<y<<' '<<#z<<"="<<z<<endl;
    12 
    13 //Standfor Yufenglin
    14 #define LL long long
    15 #define LB long double
    16 #define reg register
    17 #define il inline
    18 #define inf 1000000000
    19 #define maxn 250
    20 #define maxm 1005
    21 
    22 struct pot
    23 {
    24     int v,id;
    25 };
    26 int n,m,q;
    27 pot c[maxn+5];
    28 int dis[maxn+5][maxn+5],f[maxn+5][maxn+5],pre[maxn+5];
    29 
    30 bool cmp(pot x,pot y)
    31 {
    32     if(x.v==y.v) return x.id<y.id;
    33     return x.v<y.v;
    34 }
    35 int main()
    36 {
    37     scanf("%d%d%d",&n,&m,&q);
    38     for(int i=1;i<=n;i++)
    39     {
    40         scanf("%d",&c[i].v);
    41         c[i].id=i;
    42     }
    43     sort(c+1,c+n+1,cmp);
    44     for(int i=1;i<=n;i++)
    45     {
    46         pre[c[i].id]=i;
    47     }
    48     memset(dis,0x1f,sizeof(dis));
    49     memset(f,0x1f,sizeof(f));
    50     for(int i=1;i<=m;i++)
    51     {
    52         int x,y,z;
    53         scanf("%d%d%d",&x,&y,&z);
    54         dis[pre[x]][pre[y]]=dis[pre[y]][pre[x]]=min(dis[pre[x]][pre[y]],z);
    55     }
    56     for(int i=1;i<=n;i++) dis[i][i]=0;
    57     for(int k=1;k<=n;k++)
    58     {
    59         for(int i=1;i<=n;i++)
    60         {
    61             for(int j=1;j<=n;j++)
    62             {
    63                 if(i==j) continue;
    64                 dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]);
    65                 f[i][j]=min(f[i][j],dis[i][j]+max(c[i].v,max(c[j].v,c[k].v)));
    66             }
    67         }
    68     }
    69     for(int i=1;i<=q;i++)
    70     {
    71         int x,y;
    72         scanf("%d%d",&x,&y);
    73         printf("%d
    ",f[pre[x]][pre[y]]);
    74     }
    75     return 0;
    76 }
  • 相关阅读:
    数据泵使用笔记与相关shell
    手动创建数据库
    归档日志小试
    SQL语句的结果如何反映在SGA与磁盘中
    oracle 表空间
    linux 循环判断、数组、循环
    oracle 连接方式
    Changing Project Binding to Surround SCM Integration Provider with Visual Studio 2010
    On Caching and Evangelizing SQL
    Windows下使用python3 + selenium实现网页自动填表功能
  • 原文地址:https://www.cnblogs.com/yufenglin/p/10702998.html
Copyright © 2020-2023  润新知