zoukankan      html  css  js  c++  java
  • BZOJ1774: [Usaco2009 Dec]Toll 过路费

    n<=250个点m<=10000边无自环图,有点权边权,Q<=10000个询问i到j的最短路。这里的路径长度指路上边权和+路上点权最大值。

    n这么小,询问这么多,那就跑跑floyd吧!f[i][j]记最短路,g[i][j]记最短路上最大点权,当f[i][j]+g[i][j]>f[i][k]+f[k][j]+max(g[i][k],g[k][j])时更新答案,注意不要用无效状态即可。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 #include<math.h>
     5 #include<iostream>
     6 using namespace std;
     7  
     8 int n,m,q;
     9 #define maxn 261
    10 int f[maxn][maxn],g[maxn][maxn];
    11 int x,y,v;
    12 const int inf=5e8;
    13 int max(int a,int b) {return a>b?a:b;}
    14 int min(int a,int b) {return a<b?a:b;}
    15 int main()
    16 {
    17     scanf("%d%d%d",&n,&m,&q);
    18 //  for (int i=1;i<=n;i++)
    19 //      for (int j=1;j<=n;j++)
    20 //          g[i][j]=inf;
    21     memset(g,0,sizeof(g));
    22     for (int i=1;i<=n;i++) scanf("%d",&g[i][i]);
    23     for (int i=1;i<=n;i++)
    24     {
    25         for (int j=1;j<=n;j++)
    26             f[i][j]=inf;
    27         f[i][i]=0;
    28     }
    29     for (int i=1;i<=m;i++)
    30     {
    31         scanf("%d%d%d",&x,&y,&v);
    32         g[x][y]=max(g[x][x],g[y][y]);
    33         g[y][x]=max(g[x][x],g[y][y]);
    34         f[x][y]=min(f[x][y],v);
    35         f[y][x]=min(f[y][x],v);
    36     }
    37 //  for (int i=1;i<=n;i++){
    38 //      for (int j=1;j<=n;j++)
    39 //          cout<<f[i][j]<<' ';cout<<endl;}cout<<endl;
    40 //  for (int i=1;i<=n;i++){
    41 //      for (int j=1;j<=n;j++)
    42 //          cout<<g[i][j]<<' ';cout<<endl;}cout<<endl;
    43     for (int k=1;k<=n;k++)
    44         for (int i=1;i<=n;i++)
    45             for (int j=1;j<=n;j++)
    46                 if (!g[i][j] || (g[i][k] && g[k][j] && f[i][j]+g[i][j]>f[i][k]+f[k][j]+max(g[i][k],g[k][j])))
    47                 {
    48                     f[i][j]=f[i][k]+f[k][j];
    49                     g[i][j]=max(g[i][k],g[k][j]);
    50                 }
    51 //  for (int i=1;i<=n;i++){
    52 //      for (int j=1;j<=n;j++)
    53 //          cout<<f[i][j]<<' ';cout<<endl;}cout<<endl;
    54 //  for (int i=1;i<=n;i++){
    55 //      for (int j=1;j<=n;j++)
    56 //          cout<<g[i][j]<<' ';cout<<endl;}cout<<endl;
    57     for (int i=1;i<=q;i++)
    58     {
    59         scanf("%d%d",&x,&y);
    60         printf("%d
    ",f[x][y]+g[x][y]);
    61     }
    62     return 0;
    63 }
    View Code

    错误!本题中的最短路,枚举中转点顺序的不同会产生不同的答案。观察下图,4-5的“最短路”是2+4+9+10=25,而这需要先用到路径1-3-5(以3为中转点),再以1为中转点更新答案。

    不过本题的“最短路”是有赖于图的最短路的,在最短路可以随便枚举中转点的前提下,优先考虑小权点会使最优答案被及时地更新。就是说,f[i][j]记最短路,g[i][j]记答案,从小权点到大权点枚举中转点,一边更新答案。

    当然最后不要忘了有重边。。。。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 #include<math.h>
     5 //#include<iostream>
     6 using namespace std;
     7 
     8 int n,m,q;
     9 #define maxn 261
    10 int f[maxn][maxn],g[maxn][maxn];
    11 int x,y,v;
    12 const int inf=1e9;
    13 int max(int a,int b) {return a>b?a:b;}
    14 int min(int a,int b) {return a<b?a:b;}
    15 int a[maxn];
    16 struct Point{int id,v;bool operator < (const Point &b) const {return v<b.v;}}p[maxn];
    17 int main()
    18 {
    19     scanf("%d%d%d",&n,&m,&q);
    20     for (int i=1;i<=n;i++)
    21         for (int j=1;j<=n;j++)
    22             f[i][j]=g[i][j]=inf;
    23     for (int i=1;i<=n;i++)
    24     {
    25         scanf("%d",&a[i]);
    26         g[i][i]=p[p[i].id=i].v=a[i];
    27         f[i][i]=0;
    28     }
    29     sort(p+1,p+1+n);
    30     for (int i=1;i<=m;i++)
    31     {
    32         scanf("%d%d%d",&x,&y,&v);
    33         if (v<f[x][y]) f[x][y]=f[y][x]=v;
    34     }
    35     for (int k=1;k<=n;k++)
    36         for (int i=1;i<=n;i++)
    37             for (int j=1;j<=n;j++)
    38             {
    39                 int x=p[k].id;
    40                 f[i][j]=min(f[i][j],f[i][x]+f[x][j]);
    41                 g[i][j]=min(g[i][j],f[i][j]+max(p[k].v,max(a[i],a[j])));
    42             }
    43     for (int i=1;i<=q;i++)
    44     {
    45         scanf("%d%d",&x,&y);
    46         printf("%d
    ",g[x][y]);
    47     }
    48     return 0;
    49 }
    View Code
  • 相关阅读:
    自己回答自己的问题
    作业5 四则运算 测试与封装 5.1 5.2
    2015430 加法阶段一的封装测试
    20150423 提问2
    Java 泛型中的<? super T>和<? extends T>
    ssh 查看端口占用
    Java 回调
    SpringMVC4+MyBaits3配置
    Selenium 远程执行和监听类
    Intellij idea主题
  • 原文地址:https://www.cnblogs.com/Blue233333/p/7452727.html
Copyright © 2011-2022 走看看