【bzoj1774-过路费】floyd+排序

题意:n个点,m条双向边,每个点有权值c[i],每条边有权值a[i].d,一条路径的费用=每条边的权值和+各个点的权值的最大值,即sigma(a[i].d)+max(c[i])。q个询问,问x到y的最小费用。n<=250,m<=10000.

题解:

 1 for(int k=1;k<=n;k++)
 2  {
 3   int x=p[k].id;
 4   for(int i=1;i<=n;i++)
 5    for(int j=1;j<=n;j++)
 6    {
 7     int t0=maxx(w[i],w[x]),t1=maxx(w[x],w[j]);
 8     dis[i][j]=minn(dis[i][j],dis[i][x]+dis[x][j]-t0-t1+maxx(t0,t1));
 9    }
10  }

点按ci排序,k循环按点从小到达循环,floyd的三重循环中,k限定了当前任意的i到j的最短路径都是由1~k所更新的,也就是i到j的路径中不经过c[x]>c[k]的点。所以我们可以知道当前更新dis[i][j]的dis[i][k]和dis[k][j]这两条路径中点权的最大值分别是什么。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<queue>
 7 #include<vector>
 8 #include<cmath>
 9 #include<deque>
10 using namespace std;
11 
12 const int N=300,INF=(int)1e9;
13 int n,m,Q;
14 int w[N],dis[N][N];
15 struct node{
16     int id,d;
17 }p[N];
18 
19 int minn(int x,int y){return x<y ? x:y;}
20 int maxx(int x,int y){return x>y ? x:y;}
21 bool cmp(node x,node y){return x.d<y.d;}
22 
23 void floyd()
24 {
25     for(int k=1;k<=n;k++)
26     {
27         int x=p[k].id;
28         for(int i=1;i<=n;i++)
29             for(int j=1;j<=n;j++)
30             {
31                 int t0=maxx(w[i],w[x]),t1=maxx(w[x],w[j]);
32                 dis[i][j]=minn(dis[i][j],dis[i][x]+dis[x][j]-t0-t1+maxx(t0,t1));
33             }
34     }
35 }
36 
37 int main()
38 {
39     // freopen("a.in","r",stdin);
40     freopen("toll.in","r",stdin);
41     freopen("toll.out","w",stdout);
42     scanf("%d%d%d",&n,&m,&Q);
43     int x,y,d;
44     for(int i=1;i<=n;i++) 
45     {
46         scanf("%d",&w[i]);
47         p[i].id=i;p[i].d=w[i];
48     }
49     sort(p+1,p+1+n,cmp);
50     for(int i=1;i<=n;i++)
51         for(int j=1;j<=n;j++) 
52         {
53             if(i==j) dis[i][j]=w[i];
54             else dis[i][j]=INF;
55         }
56     for(int i=1;i<=m;i++)
57     {
58         scanf("%d%d%d",&x,&y,&d);
59         dis[x][y]=minn(dis[x][y],d+maxx(w[x],w[y]));
60         dis[y][x]=minn(dis[y][x],d+maxx(w[x],w[y]));
61     }
62     floyd();
63     // for(int i=1;i<=n;i++)
64         // for(int j=1;j<=n;j++) 
65             // printf("dis %d %d = %d
",i,j,dis[i][j]);
66     for(int i=1;i<=Q;i++)
67     {
68         scanf("%d%d",&x,&y);
69         printf("%d
",dis[x][y]);
70     }
71     return 0;
72 }
原文地址:https://www.cnblogs.com/KonjakJuruo/p/5998120.html