【[USACO09DEC]牛收费路径Cow Toll Paths】

很妙的一道题,我之前一直是用一个非常暴力的做法

就是枚举点权跑堆优化dijkstra

但是询问次数太多了

于是一直只有50分

今天终于做了这道题,不贴代码了,只说一下对这道题的理解

首先点权和边权不能混在一起,这是公认的,毕竟这个样子完全没有办法处理

那我们为什么要排序呢,发现其余几篇题解好像也没讲清楚

说得好像我能讲清楚一样

我们对于所有点按点权进行了一个排序,这一点很令人玩味,这是为什么呢

首先我们的floyd的枚举是长这个样子的

for(re int k=1;k<=n;k++)
for(re int i=1;i<=n;i++)
for(re int j=1;j<=n;j++)

最外层枚举的\(k\)是枚举的什么

中转点啊

那我们排序完了之后说明什么

说明我们中转点加入的顺序是从小到大的

于是我们在找\(i\),\(j\)之间的最短路的时候,我们的中转点如果只是枚举到了\(k1\)

那么这又说明了什么

这说明了我们当前的\(i\),\(j\)之间的最短路中并没有点权超过\(k1\)的点

于是当前这条最短路上除去起点和终点点权最大的也就是\(k1\)

那么我们就可以这样更新了

dist[i][j]=min(dist[i][j],d[i][j]+max(nm[k].d,max(nm[i].d,nm[j].d)))

这是从楼下的那位大佬代码里抄来的

怎么说呢

我们当前的k越大,说明我们的最短路中可能的中转点越多,最短路也就越短(尽管可能随着\(k\)增大最短路并不会变短,而是不变),但是同时我们加入的中转点的点权也越来越大

也就是说我们每次新加入一个中转点,可能最短路是变短了,但是我们的点权最大值也增加了,这个时候就要与前面的dist值取一个最小了

于是代码就不贴了

posted @ 2019-01-02 12:05  asuldb  阅读(186)  评论(0编辑  收藏  举报