题目
【问题描述】
精灵最近在农场上泛滥,他们经常会阻止牛们从农庄(牛棚1)走到别的牛棚(牛i的目的地是牛棚i)。每一个精灵只认识牛i并且知道牛i一般走到牛棚i的最短路径。所以他们在牛i到牛棚i之间的最后一条牛路上等牛i。当然,牛不愿意遇到精灵,所以准备找一条稍微不同的路径从牛棚1走到牛棚i。请你为每一头牛i找出避免精灵的最短路径长度。
和往常一样,农场上有 n 个牛棚(编号为1..n), m 条双向牛路(编号为 1..m)把牛棚连接起来,能让所有牛到达它们的目的地。牛路 i 连接牛棚 ai 和 bi(1<=ai,bi<=N)并且需要时间 ti(1<=ti<=1000)通过。没有两条牛路连接同样的牛棚,所有牛路满足 ai!=bi。所有数据中,牛 i 使用的牛棚 1 到牛棚 i 的最短路径是唯一的。
【输入格式】
第一行包含两个空格分开的整数:n,m。之后的 m 行,每行包含三个空格分开的数ai,bi,ti,表示一条牛路连接的 ai,bi 两个牛棚,通过这条牛路的时间为 ti。
【输出格式】
第 1 到 n-1 行:第 i 行包含一个数,从牛棚 1 到牛棚 i+1 并且避免从牛棚 1 到牛棚 i+1 最短路径上最后一条牛路的最少的时间。如果这样的路径不存在,输出 -1。
【输入样例】
4 5
1 2 2
1 3 2
3 4 4
3 2 1
2 4 3
【输出样例】
3
3
6
【数据范围】
3<=n<=100000 2<=m<=200000
分析
这道题真的是很好很好的题目
感觉可能思维难度甚至比天天爱跑步还要大,在方法正确的前提下代码量略少
首先来看正解思路
1、最短路径唯一,因此我们要用最短路径生成树
最短路径生成树哎!!!虽然听说过但我第一次用
2、既然是生成树,那么我们就想到加边然后LCA
每次次LCA我们都可以使得那个环上除了LCA外的所有点得到一个最短路外的其他路
这里我们还要先分析:对于次短路,只有一条边不是最短路径生成树上的边
3、这里倍增如果用逐步爬山法并且每次都更新肯定会超时,我们先化简一下表达式
对于一个点它的更新值是dist[u]+dist[v]+w-dist[z],前面三个都只和添加的边有关系
4、由此我们可以直接排序,按照dist[u]+dist[v]+w从小到大排序,这样每个点只需要修改一次
5、如果一个点已经被修改过了,我们就让它指向它的第一个可能需要修改的结点,对于条新增边来说就是它的
LCA(因为不会影响到LCA本身),就变成了大步跳跃,加上路径压缩,实际就是并查集
然后答案就出来啦。。。太太太牛批了
最短路径生成树+LCA+排序+大步跳跃,1,3都是我很不熟悉的,感觉收获良多
再说说怎么被天天爱跑步误导的,因为对于每一条新增的边我们都可以拆成两段。。。
然后就可以用优先队列维护。。。
但是由于不能及时删除,而且RMQ又不能像计数问题一样找一个改变量
然后我觉得可以用线段树呀!!可是少主不会树链剖分呜呜呜呜~~~
(也暂时不打算学^~^)
同时也验证了:不能瞎联想题,不能主观臆断,每道题最好的做法是题目本身,不然写得又多还要错,特别是 对于没有见过的题目,根本无法把握到本质,也不清楚本质和你联想的那道题究竟是不是一样的 而题目又不会完全一样,你也不知道该学到哪一步,