CF1486E Paired Payment

w怎么这么小啊。

正解就是加点虚点来改造图。注意,根据规则,我们一次性走两条边,因此这两条边可以分类为,第一条边,第二条边。

u从第一条边走到v后,v只能走第二条边走到x,而不能走第一条边走到别人。

为了实现这一点,即第一条边走完后只能走第二条边,我们可以参考网络流中的边的设计,把点v拆成e(v)(v的边数)个点,然后u到这e(v)个点的边权即为(w(u,v)+w(v,x))^2 ,其中x是e(v)条边的一条边权。

(因为v的边权很多可能相等,我们不重复添加虚点,因此对每个v添加的虚点个数不是O(e(v))而是O(w)的)

然后对于这w个点,它所连的边即为第二条边,权重设为0,连到正常点上。这样总共添加了O(M)个点(按照O(e(v))之和计算的话),对于新图跑Dijkstra即可。

之前我的一个想法,就是把边和点的互换,边变为点,但这样一来,原先v的所有边之间都得连上边,就会造成O(M^2)次连边。这样没利用到w很小这个性质。

 

等等,前面我胡说了些神马,如果这给第一条边附上权重,可能第二条边就不是走到我们的目的地了,万一人家骗了更小的运费走到别的地方去了呢。

所以我们应该给第二条边附上权重,并且保证第一条边走到的中间点(虚点)只能走第二条边走出去。

所以本质上,就是,原来的Dijkstra,我们从一个点出发,只知道这个点的信息,对于它是从何处走来的,之前一条边是什么,我们不记录。

现在,我们设置虚点,每个虚点都反映了上一条边是从何处走来的信息(准确地说,是上一边的权值,这是我们真正关心的,具体从哪里走来的还真不能记录,那样会导致O(NM)的点数)

因为权值w很小,所以算法是可行的。

 

posted @ 2021-03-26 20:19  AngelKnows  阅读(90)  评论(0)    收藏  举报