洛谷 2966 2966 [USACO09DEC]牛收费路径Cow Toll Paths

【题意概述】

  给出一个图,点有正点权,边有正边权,通过两点的代价为两点间的最短路加上路径通过的点的点权最大值。

  有M个询问,每次询问通过两点的代价。

【题解】

  先把点按照点权从小到大排序,然后按照这个顺序跑floyed.  这样的话当前路径i-->k-->j的点权最大值只会在i,j,k中产生,用一个ans[i][j]数组维护代价即可。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #define LL long long
 5 #define rg register
 6 #define N 300
 7 using namespace std;
 8 int n,m,q,f[N][N],ans[N][N],poi[N];
 9 struct rec{
10     int c,num;
11 }a[N];
12 inline int read(){
13     int k=0,f=1; char c=getchar();
14     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
15     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
16     return k*f;
17 }
18 inline void Pre(){
19     for(rg int i=0;i<=n;i++)
20         for(rg int j=0;j<=n;j++) f[i][j]=ans[i][j]=1e9;
21     for(rg int i=0;i<=n;i++) f[i][i]=ans[i][i]=0;
22 }
23 inline int mx(int a,int b,int c){
24     int t=-2e9;
25     if(a>t)t=a;
26     if(b>t)t=b;
27     if(c>t)t=c;
28     return t;
29 }
30 inline bool cmp(rec a,rec b){return a.c<b.c;}
31 int main(){
32     n=read(); m=read(); q=read();
33     Pre();
34     for(rg int i=1;i<=n;i++) a[i].c=read(),a[i].num=i;
35     sort(a+1,a+1+n,cmp);
36     for(rg int i=1;i<=m;i++){
37         int u=read(),v=read();
38         f[u][v]=f[v][u]=min(f[u][v],read());
39     }
40     for(rg int k=1;k<=n;k++)
41         for(rg int i=1;i<=n;i++)
42             for(rg int j=1;j<=n;j++){
43                 int K=a[k].num,I=a[i].num,J=a[j].num;
44                 f[I][J]=f[J][I]=min(f[I][J],f[I][K]+f[K][J]);
45                 ans[I][J]=ans[J][I]=min(ans[I][J],f[I][J]+mx(a[i].c,a[j].c,a[k].c));
46             }
47     while(q--){
48         int u=read(),v=read();
49         printf("%d\n",ans[v][u]);
50     }
51     return 0;
52 }
View Code

 

posted @ 2018-08-03 06:54  Driver_Lao  阅读(117)  评论(0编辑  收藏  举报