[USACO 18Dec Gold] Fine Dining

题目大意:

  给定n个顶点m条有权值的边。除了第n个点外每个顶点上有一头牛。有k个顶点上有美味值为y[i]的草。每头牛都需要到达点n,且在路上可以吃有且仅有的一捆草,如果这样需要走的路程比最短路程多的部分不超过该草的美味值。判断每头牛是否能吃到草。

  2<=n<=50,000; 1<=k<=n; 1<=m<=100,000

题目解法:

  首先我们想到第i头牛可以吃到草 当且仅当存在一个k使得 dis[i][k]+dis[k][n]-y[k]<=dis[i][n]。观察题目数据范围,对于每个i我们显然无法枚举所有k,因此我们需要寻找将这个判断式中一切和k相关的项替换掉的方法。首先我们可以观察到对于每个i我们都需要dis[i][n]。因此我们显然需要跑一遍以n为起点到所有顶点的最短路。我们用f[i]表示f[i][n]记录这类最短路。

  再考虑前面的 dis[i][k]+dis[k][n], 我们发现它和f[i]很像,区别仅为这是一条从i到n必须经过有草的点的最短路径。既然必须经过,我们不妨将这k个点直接作为起点跑最短路,因为dis[k][n]为我们已知的f[k],我们只需要在继续求出这k个点到其他点的最短路径即可。我们设这时的最短路为g[i],表示从i到n经过有草的点的最短路径。

  这时式子已经化成了g[i]-y[k]<=dis[i][n]。只剩一项y[k]仍然十分棘手。我们考虑把它归到g的计算中。显然,我们可以在初始化有草的k个点的g值时将g[i]设为f[i]-y[i]。这样的g[i]就可以直接代替原来的g[i]-y[k],式子化为g[i]<=dis[i],达成了O(1)查询的目标。

  两遍dijkstra。总的复杂度是O(m log n)。

猜你喜欢

转载自www.cnblogs.com/myrcella/p/12228883.html