6.12友谊赛T4城市交通费题解

与普通的最短路径不同的是,题目中新引入了一个计入总体的费用——城市建设费。由于城市建设费由整体的某最大值决定,导致解没有最优子结构的性质,给思维带来难度。

既然最棘手的是城市建设费,我们就对它分类讨论。为了分类有效,我们先把城市繁华度从小到大排个序,这样分类讨论时当前路径的城市的最大繁华度即为不严格递增的。这样,我们便可以考虑当前路径只可能经过前k个最不繁华的城市(可以不经过,但只要经过,经过的城市就一定在那前k个最不繁华的城市中),让k从小到大递增(每次+1)至n,对于每个k值,更新一下最短路径,再看一下第k个最不繁华的城市是否可以更新答案。由此我们想到了FLOYD算法。

见AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cctype>
 5 #include<cstring>
 6 
 7 using namespace std;
 8 
 9 int ans,n,m,q,a[251][251],f[251][251],p[251],t[251];
10 
11 char ch;
12 
13 int read()
14 {
15     ans=0;
16     ch=getchar();
17     while(!isdigit(ch)) ch=getchar();
18     while(isdigit(ch)) ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
19     return ans;
20 }
21 
22 int cmp(int x,int y)//排序最终效果:把t数组排序,使t数组满足编号为ti的城市是第i个最不繁华的城市 
23 {
24     return p[x]<p[y];    
25 }
26 
27 int main()
28 {
29 //    freopen("road.in","r",stdin);
30 //    freopen("road.out","w",stdout);
31     memset(a,63,sizeof a);//把a数组(存两点间最短路径)初始化为一个足以解题的无穷大 
32     n=read(),m=read(),q=read();
33     for(int i=1;i<=n;i++) p[i]=read();
34     for(int i=1;i<=n;i++) t[i]=i;//一开始t数组应有所有城市的编号,所以不能忘了初始化
35     int u,v,w;
36     for(int i=1;i<=m;i++)
37     {
38         u=read(),v=read(),w=read();
39         a[u][v]=min(a[u][v],w);//用邻接矩阵存边不要忘了防重边
40         a[v][u]=min(a[v][u],w);
41     }
42     for(int i=1;i<=n;i++) a[i][i]=0;
43     for(int i=1;i<=n;i++) //初始化两城市直接连通(路径不经过其他任何城市)的情况 
44         for(int j=1;j<=n;j++)
45         f[i][j]=a[i][j]+max(p[i],p[j]);
46     sort(t+1,t+1+n,cmp);
47     for(int k=1;k<=n;k++)//当FLOYD的最外层循环枚举到k是,路径经过的中间城市只可能是前k个最不繁华的城市(因为目前只用他们进行了松弛操作) 
48         for(int i=1;i<=n;i++)
49             for(int j=1;j<=n;j++)
50             {
51                 a[i][j]=min(a[i][j],a[i][t[k]]+a[t[k]][j]);
52                 f[i][j]=min(f[i][j],a[i][j]+max(p[i],max(p[j],p[t[k]])));
53             }
54     for(int i=1;i<=q;i++)
55     {
56         u=read();v=read();
57         printf("%d\n",f[u][v]);
58     }
59     return 0;
60 }

总结:算法中有很多细节。初始时的边界条件要记得考虑。如果一开始对某个变量的有要求,就不能忘了初始化。用邻接矩阵存边的话不要忘了去重边。

 

posted @ 2019-06-13 09:01  千叶繁华  阅读(162)  评论(0编辑  收藏  举报