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

暴力的想法是
\[ f[i][j]=\min\{f[i][k]+f[k][j]\}\\ g[i][j]=f[i][j]+\max\{val[i],val[j],val[k]\} \]
但是这样并不能保证真的取到路径上的点权最大值,Floyd中的k并没有给我们什么好的性质

但是Floyd的拓扑序是人定的,只是习惯从1到\(n\)而已

因此我们按点权排序,保证点权递增,这个式子就是正确的了

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>

using namespace std;

inline int rd(){
  int ret=0,f=1;char c;
  while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
  while(isdigit(c))ret=ret*10+c-'0',c=getchar();
  return ret*f;
}
#define space putchar(' ')
#define nextline putchar('\n')
void _(int x){if(!x)return;_(x/10);putchar('0'+x%10);}
void out(int x){if(!x)putchar('0');_(x);}

const int MAXN = 300;

int f[MAXN][MAXN],g[MAXN][MAXN];
int val[MAXN],id[MAXN];
int n,m,q;

inline void upmin(int &x,int y){x=min(x,y);}

bool cmp(int x,int y){
  return val[x]<val[y];
}

int main(){
  memset(f,0x3f,sizeof(f));
  memset(g,0x3f,sizeof(g));
  n=rd();m=rd();q=rd();
  for(int i=1;i<=n;i++)val[i]=rd();
  int x,y;
  for(int i=1;i<=m;i++){
    x=rd();y=rd();
    f[x][y]=f[y][x]=min(f[x][y],rd());
  }
  for(int i=1;i<=n;i++)id[i]=i,f[i][i]=0;
  sort(id+1,id+1+n,cmp);
  for(int _k=1;_k<=n;_k++){
    int k=id[_k];
    for(int _i=1;_i<=n;_i++){
      int i=id[_i];
      for(int _j=1;_j<=n;_j++){
        int j=id[_j];
        upmin(f[i][j],f[i][k]+f[k][j]);
        upmin(g[i][j],f[i][j]+max(val[k],max(val[i],val[j])));
      }
    }
  }
  for(int i=1;i<=q;i++){
    out(g[rd()][rd()]);
    nextline;
  }
  return 0;
}

猜你喜欢

转载自www.cnblogs.com/ghostcai/p/9804397.html